[WCF REST] WebHttpBinding与消息编码

不论是我们采用SOAP还是REST架构风格,运行时框架体系依然不曾改变,终结点也仍旧是通信的核心。在Web

HTTP编程模型中,我们采用基于WebHttpBinding绑定的终结点。绑定是一组相关绑定元素的有序组合,绑定的特性与能力决定于它包含的绑定元素,在这里我们通过分析绑定元素的方式来剖析WebHttpBinding绑定与其它绑定有何不同。采用HTTP/HTTPS通信协议的WebHttpBinding具有一些与WSHttpBinding/WS2007HttpBinding相同的属性,在这里我们只关心如下定义的Security属性。

   1: public class WebHttpBinding : Binding, IBindingRuntimePreferences
   2: {
   3:     //其它成员
   4:     public WebHttpSecurity Security { get; }
   5: }
   6: public sealed class WebHttpSecurity
   7: {
   8:     // 其它成员
   9:     public WebHttpSecurityMode Mode { get; set; }
  10:     public HttpTransportSecurity Transport { get; }
  11: }
  12: public enum WebHttpSecurityMode
  13: {
  14:     None,
  15:     Transport,
  16:     TransportCredentialOnly
  17: }

基于SOAP的绑定一般具有两种基本的安全模式,即Message和Transport模式。对于前者,它是完全建立在WS-Security为核心的安全协议之上的,而整个WS-*协议簇都是基于SOAP的,所以自然不能应用在WebHttpBinding上,所以它只能通过HTTPS提供针对Transport模式的安全支持。具体来说,通过枚举WebHttpSecurityMode表示的安全模式具有如下三个选项:

  • None:HTTP 请求未使用任何安全性;
  • Transport:HTTP 请求使用传输级安全性;
  • TransportCredentialOnly:仅提供基于 HTTP 的客户端身份验证。

一、WebHttpBinding的绑定元素

现在我们根据上述三种不同的安全模式创建相应的WebHttpBinding对象,然后通过如下的程序在控制台中答应出所有的绑定元素类型。

   1: static void Main(string[] args)
   2: {
   3:     WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.None);
   4:     ListBindingElements(binding);
   5:  
   6:     binding = new WebHttpBinding(WebHttpSecurityMode.Transport);
   7:     ListBindingElements(binding);
   8:  
   9:     binding = new WebHttpBinding(WebHttpSecurityMode.TransportCredentialOnly);
  10:     ListBindingElements(binding);
  11: }
  12: static void ListBindingElements(WebHttpBinding binding)
  13: {
  14:     int index = 1;
  15:     Console.WriteLine(binding.Security.Mode + ":");
  16:     foreach (var element in binding.CreateBindingElements())
  17:     { 
  18:         Console.WriteLine("{0}. {1}", index++, element.GetType().FullName);
  19:     }
  20:     Console.WriteLine();
  21: }

上述的程序执行之后会在控制台上产生如下的输出,从中我们不难看出三个WebHttpBinding均由一个消息编码元素和传输元素组成,我们知道这两种绑定元素最所有类型的绑定所必需的。

   1: None:
   2: 1. System.ServiceModel.Channels.WebMessageEncodingBindingElement
   3: 2. System.ServiceModel.Channels.HttpTransportBindingElement
   4:  
   5: Transport:
   6: 1. System.ServiceModel.Channels.WebMessageEncodingBindingElement
   7: 2. System.ServiceModel.Channels.HttpsTransportBindingElement
   8:  
   9: TransportCredentialOnly:
  10: 1. System.ServiceModel.Channels.WebMessageEncodingBindingElement
  11: 2. System.ServiceModel.Channels.HttpTransportBindingElement

对于WebHttpBinding的两个绑定元素来说,由于它通过HTTPS提供针对Transport安全的支持,所以当安全模式为Transport时对应的传输绑定元素为HttpsTransportBindingElement,对于其余两种安全模式则直接采用HttpTransportBindingElement作为传输绑定元素。现在我们着重讨论是作为消息编码绑定元素的WebMessageEncodingBindingElement类型,以及它涉及的消息编码机制。

二、消息编码

我们先来看看WebMessageEncodingBindingElement的基本的定义。如下面的代码片断所示,它是MessageEncodingBindingElement的子类,并且具有与TextMessageEncodingElement类似的属性定义。其中MaxReadPoolSize和MaxWritePoolSize表示表示无需分配新的XmlDictionaryReader/XmlDictionaryWriter便可以读取的便可同时读取/写入的最大消息数,默认值分别是64和16。ReaderQuotas属性返回用于约束读取的XML的复杂度的XmlDictionaryReaderQuotas对象,而WriteEncoding属性表示采用的字符编码类型,默认采用UTF-8编码方式。由于WebHttpBinding不使用SOAP,表示消息版本的MessageVersion属性自然返回None,如果我们对该属性进行设置,指定的属性值也只能是MessageVersion.None。

   1: public sealed class WebMessageEncodingBindingElement : MessageEncodingBindingElement,...
   2: {   
   3:     //其它成员
   4:     public override MessageEncoderFactory CreateMessageEncoderFactory();
   5:  
   6:     public bool CrossDomainScriptAccessEnabled {get; set; } 
   7:     public WebContentTypeMapper ContentTypeMapper { get; set; }
   8:  
   9:     public int MaxReadPoolSize { get; set; }
  10:     public int MaxWritePoolSize { get; set; }
  11:     public override MessageVersion MessageVersion { get; set; }
  12:     public XmlDictionaryReaderQuotas ReaderQuotas { get; }
  13:     public Encoding WriteEncoding { get; set; }
  14: }

除此之外,WebMessageEncodingBindingElement具有CrossDomainScriptAccessEnabled
和ContentTypeMapper这两个重要的属性。前者表示是否支持跨域(Corss-Domain)脚本访问,默认值为False。后者类型为WebContentTypeMapper。WebContentTypeMapper用于进行消息的内容类型(Content Type,有时候也成为媒体类型或者MIME类型)与具体的格式(比如XML、JSON等)之间的映射。

   1: public abstract class WebContentTypeMapper
   2: {
   3:     protected WebContentTypeMapper();
   4:     public abstract WebContentFormat GetMessageFormatForContentType(string contentType);
   6: }
   7: public enum WebContentFormat
   8: {
   9:     Default,
  10:     Xml,
  11:     Json,
  12:     Raw
  13: }

如上面的代码所示,WebContentTypeMapper是一个抽象类,包含的唯一的抽象方法GetMessageFormatForContentType用于根据指定的内容类型返回与之匹配的通过枚举WebContentFormat表示的内容格式。WebContentFormat枚举的Xml、JSON和Raw体现了Web HTTP编程模型支持三种基本格式,其中Raw表示原始的二进制。

最终的消息编码/解码工作是通过继承自MessageEncoder的消息编码器实现的,消息编码器又是通过继承自MessageEncoderFactory的编码器工厂创建出来的,而消息编码绑定元素最终通过方法CreateMessageEncoderFactory创建了编码器工厂。对于WebMessageEncodingBindingElement来说,它的CreateMessageEncoderFactory方法会创建一个具有如下定义的WebMessageEncoderFactory对象。

   1: internal class WebMessageEncoderFactory : MessageEncoderFactory
   2: {
   3:     public WebMessageEncoderFactory(Encoding writeEncoding, int maxReadPoolSize,int maxWritePoolSize, XmlDictionaryReaderQuotas quotas, 
   4:         WebContentTypeMapper contentTypeMapper, bool javascriptCallbackEnabled);
   5:     public override MessageEncoder Encoder { get; }
   6:     public override MessageVersion MessageVersion { get; }
   7: }
   8:   

WebMessageEncoderFactory是一个继承自MessageEncoderFactory的内部类型。除了布尔类型的参数javascriptCallbackEnabled对应着WebMessageEncodingBindingElement的属性CrossDomainScriptAccessEnabled之外,WebMessageEncoderFactory的构造函数参数与WebMessageEncodingBindingElement的同名属性一一对应。代表消息版本的MessageVersion属性依然返回None,而真正用于最终消息编码/解码工作的是通过Encoder属性返回的具有如下定义的WebMessageEncoder对象。

   1: internal class WebMessageEncoderFactory : MessageEncoderFactory
   2: {    
   3:     private class WebMessageEncoder : MessageEncoder
   4:     {
   5:         //其他成员
   6:         private MessageEncoder TextMessageEncoder { get; }
   7:         private MessageEncoder JsonMessageEncoder { get; }
   8:         private MessageEncoder RawMessageEncoder { get; }
   9:     }
  10: }

如上面的代码片断所示,WebMessageEncoder实际上是内嵌于WebMessageEncoderFactory类型中继承自MessageEncoder的内部类型。WebMessageEncoder本身并不真正地实施消息的编码/解码,最终的消息编码/解码工作是通过三个属性TextMessageEncoder、JsonMessageEncoder和RawMessageEncoder体现的具体消息编码器完成的,而它们又分别对应着通过WebContentFormat枚举表示的三种内容类型Xml、JSON和Raw。

作者:蒋金楠
微信公众账号:大内老A
微博:www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文链接

时间: 2024-10-07 08:46:01

[WCF REST] WebHttpBinding与消息编码的相关文章

《WCF技术内幕》翻译9:第1部分_第2章_面向服务:消息编码

消息编码 随着时间的流逝,也许我们会条件反射式地认为XML(SOAP)是一个结构文本 .毕竟,文本是人可读的,每个计算机系统也可以处理文本.基于文本的XML的 普遍共性与我们的与其它系统交互的想法产生了共鸣.可以容易的解释的基于文 本的XML本质上会体积变大.可以理解使用XML会带来性能损失.就像要花费点精 力把信装到信封里一样,它需要一些处理时间与XML交互.某些情况下,基于文 本的XML数据大小限制了它的应用,特别是当我们要通过网络发送一个XML消息的 时候. 此外,如果我们限制自己使用基于

WCF专题系列(3):深入WCF寻址Part 3—消息过滤引擎

概述 通过前面两篇的介绍,对Web服务寻址规范以及在WCF开发中终结点地 址有了深入的认识.本文我们继续深入WCF寻址第三部分内容,当消息传入时, 如何来确定匹配的终结点,就是我们本文要讲到的消息筛选引擎.在WCF中,消 息筛选器引擎包括两个重要的组成部分:筛选器和筛选器表. 认识消息 筛选器 在WCF中当有消息传入时,它使用消息筛选器来确定匹配的终结点,每 个终结点实际上关联着两个筛选器:一个地址筛选器和一个契约筛选器.地址筛 选器确定传入消息是否匹配终结点的"To"地址和任何必需的

WCF分布式开发步步为赢(13):WCF服务离线操作与消息队列MSMQ

之前曾经写过一个关于MSMQ消息队列的文章:WCF分布式开发必备知识 (1):MSMQ消息队列 ,当时的目的也是用它来作为学习WCF 消息队列MSMQ编程的 基础文章.在那篇文章里,我们详细介绍了MSMQ消息队列的基本概念.安装.部 署.开发.调试等相关问题.今天我们来学习WCF分布式开发步步为赢(13):WCF 服务离线操作与消息队列MSMQ.在WCF框架下使用MSMQ消息队列服务编程. 这 里我会给出一个使用WCF MSMQ实现离线请求的DEMO示例程序. 全文结构是:[1]MSMQ基本概念

wcf-多个WCF调用同一个MSMQ消息队列

问题描述 多个WCF调用同一个MSMQ消息队列 多个WCF调用同一个MSMQ消息队列可以实现吗?配置文件应该怎么写?求大神多多帮忙啊~我是个新手,希望大神们能尽快给我答案,最好详细些,谢谢了~ 解决方案 http://www.cnblogs.com/quietwalk/archive/2011/08/10/2133241.html 多个和一个没区别. 解决方案二: 天生消息队列就是跨进程的.

[老老实实学WCF] 第十篇 消息通信模式(下) 双工

原文:[老老实实学WCF] 第十篇 消息通信模式(下) 双工 老老实实学WCF 第十篇 消息通信模式(下) 双工   在前一篇的学习中,我们了解了单向和请求/应答这两种消息通信模式.我们知道可以通过配置操作协定的IsOneWay属性来改变模式.在这一篇中我们来研究双工这种消息通信模式.   在一定程度上说,双工模式并不是与前面两种模式相提并论的模式,双工模式的配置方法同前两者不同,而且双工模式也是基于前面两种模式之上的.   在双工模式下,服务端和客户端都可以独立地调用对方,谁都不用等待谁的答复

WCF技术剖析之十九:深度剖析消息编码(Encoding)实现(下篇)

通过上篇的介绍,我们知道了WCF所有与编码与解码相关的功能都实现在相应的System.Xml.XmlDictionaryWriter和System.Xml.XmlDictionaryReader中.但是在真正的WCF处理框架中,却并不直接使用XmlDictioanryWriter和XmlDictionaryReader对象,而通过相应的消息编码器(System.ServiceModel.Channels.MessageEncoder)对其进行进一步封装,专门用于消息的编码和解码. 一.消息编码器

WCF REST系列文章汇总(共9篇)

[01] 一个简单的REST服务实例 [02] WebHttpBinding与消息编码 [03] Web消息主体风格(Message Body Style) [04] 帮助页面与自动消息格式(JSON/XML)选择 [05] WebServiceHost有何特别之处? [06] UriTemplate.UriTemplateTable与WebHttpDispatchOperationSelector [07] 通过ASP.NET Output Caching实现声明式缓存 [08] 提高性能的一

[WCF REST] 帮助页面与自动消息格式(JSON/XML)选择

可以说WebHttpBinding和WebHttpBehavior是整个Web HTTP编程模型最为核心的两个类型,前者主要解决消息编码问题,而余下的工作基本上落在了终结点行为WebHttpBehavior上.WebHttpBehavior属性HelpEnabled和AutomaticFormatSelectionEnabled是"帮助页面"与"自动消息格式选择"这两个特性的总开关.["自动消息格式(JSON/XML)选择"源代码从这里下载] 1

WCF专题系列(6):消息如何传递之绑定Part 1

什么是绑定 从本质上说,WCF是一个通信服务框架,它允许我们使用不同 的传输协议(如Http.Https.TCP.P2P.IPC和MSMQ等),使用不同的消息编码 形式(文本.二进制和MTOM),跟不同的WS-*系列规范(如WS-Security.WS- Atomic Transaction等)交互.所有这些细节都是由通道堆栈来处理的,看一下 Aaron Skonnard给出的这幅图: 图1 最底层传输组件读入消息,消息编码器将传入字节读取为 逻辑消息对象,之后消息通过通道堆栈中的各个消息,它们