对于Web HTTP编程模型来说,服务契约中作为操作的方法无须应用OperationContractAttribute特性,只需要根据需要应用WebGetAttribute与WebInvokeAttribute特性即可。前者针对GET HTTP方法,或者则针对其他HTTP方法。WebGetAttribute与WebInvokeAttribute的属性BodyStyle和IsBodyStyleSetExplicitly涉及到“Web消息主体风格”的话题。

   1: [AttributeUsage(AttributeTargets.Method)]

   2: public sealed class WebGetAttribute : Attribute, IOperationBehavior

   3: {

   4:     //其他成员

   5:     public WebMessageBodyStyle BodyStyle { get; set; }

   6: }

   7:  

   8: [AttributeUsage(AttributeTargets.Method)]

   9: public sealed class WebInvokeAttribute : Attribute, IOperationBehavior

  10: {

  11:     //其他成员

  12:     public WebMessageBodyStyle BodyStyle { get; set; }

  13: }

至于消息主体的风格通过具有如下定义的枚举WebMessageBodyStyle表示。

   1: public enum WebMessageBodyStyle

   2: {

   3:     Bare,

   4:     Wrapped,

   5:     WrappedRequest,

   6:     WrappedResponse

   7: }

我们知道请求消息和回复消息分别是对操作方法输入参数和返回值(输出参数和引用参数)的封装,WebMessageBodyStyle中的Bare表示请求消息和回复消息的主体部分仅仅包含针对输入参数和返回值(输出参数和引用参数)序列化后的内容,而Wrapped则会在外面包装一个基于当前操作的“封套”。枚举项WrappedRequest和WrappedResponse用于单独针对请求消息和回复消息的主体进行封装。

WebGetAttribute与WebInvokeAttribute的属性BodyStyle的默认值为Bare。如果该属性被设置成WrappedRequest,则回复消息主体依然采用Bare风格;如果该属性被设置成WrappedResponse,则请求消息主体依然采用Bare风格。布尔类型的只读属性IsBodyStyleSetExplicitly表示是否针对属性BodyStyle进行了显示设置。

目录
一、Xml+Bare
二、Xml+Wrapped
三、JSON+Bare
四、JSON+Wrapped
五、Bare请求消息风格对单一输入的限制
六、Bare回复消息风格对单一输出的限制

一、Xml + Bare

我们通过之前演示的实例来看看针对不同的消息格式(XML和JSON),请求消息和回复消息的主体在采用不同风格的情况下具有怎样的结构。现在我们对应用在契约接口IEmployees中的Create操作方法上的WebInvokeAttribute进行了如下的修改,即显式地指定了请求消息和回复消息的格式(XML)和主体风格(Bare)。同时也将返回类型从void编程了Employee,并直接将创建的Employee对象返回。

   1: [ServiceContract]

   2: public interface IEmployees

   3: {

   4:     //其他成员

   5:     [WebInvoke(UriTemplate = "/", Method = "POST", 

   6:     RequestFormat = WebMessageFormat.Xml, 

   7:     ResponseFormat = WebMessageFormat.Xml, 

   8:     BodyStyle = WebMessageBodyStyle.Bare)]

   9:     Employee Create(Employee employee);

  10: }

  11:  

  12: public class EmployeesService : IEmployees

  13: {

  14:     //其他成员

  15:     public Employee Create(Employee employee)

  16:     {

  17:         employees.Add(employee);

  18:         return employee;

  19:     }

  20: }

我们针对如下所示的代码通过服务调用添加一个姓名为“王五”的员工。

   1: using (ChannelFactory<IEmployees> channelFactory = new ChannelFactory<IEmployees>("employeeService"))

   2: {

   3:     IEmployees proxy = channelFactory.CreateChannel();

   4:     proxy.Create(new Employee

   5:     {

   6:         Id         = "003",

   7:         Name       = "王五",

   8:          Grade     = "G9",

   9:         Department = "行政部"

  10:     });           

  11: }

针对如上所示的服务调用,由于消息格式和主体风格分别为Xml和Bare,所以作为请求消息和回复消息的主体仅仅是Employee对象被序列化后生成的XML片断,具体内容如下所示。

   1: 请求消息主体:

   2: <Employee xmlns="http://www.artech.com/" 

   3:   xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

   4:   <Department>行政部</Department>

   5:   <Grade>G9</Grade>

   6:   <Id>003</Id>

   7:   <Name>王五</Name>

   8: </Employee>

   9:  

  10: 回复消息主体:

  11: <Employee xmlns="http://www.artech.com/" 

  12:   xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

  13:   <Department>行政部</Department>

  14:   <Grade>G9</Grade>

  15:   <Id>003</Id>

  16:   <Name>王五</Name>

  17: </Employee>

二、Xml + Wrapped

现在我们对契约接口略加修改,将应用在操作方法Create上的WebInvokeAttribute特性的属性BodyStyle设置为Wrapped。

   1: [ServiceContract]

   2: public interface IEmployees

   3: {

   4:     //其他成员

   5:     [WebInvoke(UriTemplate = "/", Method = "POST", 

   6:     RequestFormat = WebMessageFormat.Xml, 

   7:     ResponseFormat = WebMessageFormat.Xml, 

   8:     BodyStyle = WebMessageBodyStyle.Wrapped)]

   9:     Employee Create(Employee employee);

  10: }

针对相同的服务调用,请求消息和回复消息将具有如下所示的主体内容。我们可以看出Employee被序列化后生成的XML在请求消息中作为<Create>元素的子元素;对于回复消息来说,Employee被序列化后生成的XML的根元素名称为CreateResult,而不是<Employee>,而整个<CreateResult>内嵌于< CreateResponse >元素中。

   1: 请求消息主体:

   2: <Create xmlns="http://tempuri.org/">

   3:   <employee xmlns:a="http://www.artech.com/" 

   4:         xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

   5:     <a:Department>行政部</a:Department>

   6:     <a:Grade>G9</a:Grade>

   7:     <a:Id>003</a:Id>

   8:     <a:Name>王五</a:Name>

   9:   </employee>

  10: </Create>

  11:  

  12: 回复消息主体:

  13: <CreateResponse xmlns="http://tempuri.org/">

  14:   <CreateResult xmlns:a="http://www.artech.com/" 

  15:         xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

  16:     <a:Department>行政部</a:Department>

  17:     <a:Grade>G9</a:Grade>

  18:     <a:Id>003</a:Id>

  19:     <a:Name>王五</a:Name>

  20:   </CreateResult>

  21: </CreateResponse>

三、JSON+ Bare

上面我们通过实例演示了消息格式为Xml情况下针对不同风格的消息主体的内容差异,现在我们按照相同的方式来讨论当消息格式为JSON的时候,针对不同风格的消息主体在结构上又具有怎样差异。如下面的代码片断所示,我们通过对契约接口的修改将服务操作Create的消息格式和主体风格设置成Json和Bare。

   1: [ServiceContract]

   2: public interface IEmployees

   3: {

   4:     //其他成员

   5:     [WebInvoke(UriTemplate = "/", Method = "POST", 

   6:     RequestFormat = WebMessageFormat.Json, 

   7:     ResponseFormat = WebMessageFormat.Json, 

   8:     BodyStyle = WebMessageBodyStyle.Bare)]

   9:     Employee Create(Employee employee);

  10: }

同样针对之前的服务调用,以JSON形式表示的Employee对象将直接作为请求消息和回复消息的主体部分,具体的内容如下所示。(S1004)

   1: 请求消息主体:

   2: {"Department":"行政部","Grade":"G9","Id":"003","Name":"王五"}

   3:  

   4: 回复消息主体:

   5: {"Department":"行政部","Grade":"G9","Id":"003","Name":"王五"}

四、JSON+ Wrapped

我们最后来演示Json消息格式在Wrapped风格下具有怎样的结构,为此我们只需要将应用在Create操作方法上的WebInvokeAttribute特性的BodyStyle属性设置为Wrapped。

   1: [ServiceContract]

   2: public interface IEmployees

   3: {

   4:     //其他成员

   5:     [WebInvoke(UriTemplate = "/", Method = "POST", 

   6:     RequestFormat = WebMessageFormat.Json, 

   7:     ResponseFormat = WebMessageFormat.Json, 

   8:     BodyStyle = WebMessageBodyStyle.Wrapped)]

   9:     Employee Create(Employee employee);

  10: }

如下面的代码所示,由于请求消息和回复消息采用Wrapped风格,表示Employee的JSON对象最终作为最终JSON对象的“employee”属性和“CreateResult”属性。(S1005)

   1: 请求消息主体:

   2: {"employee":{"Department":"行政部","Grade":"G9","Id":"003","Name":"王五"}}

   3:  

   4: 回复消息主体:

   5: {"CreateResult":{"Department":"行政部","Grade":"G9","Id":"003","Name":"王五"}}

五、Bare请求消息风格对单一输入的要求

对于Bare消息主体风格来说,意味着对象被序列化后生成的XML或者JSON表示直接作为消息的主体,所以只适用于单一对象。具体来说,只有具有唯一输入参数的操作方法才能将请求消息的主题风格设置为Bare。

   1: [ServiceContract(Namespace = "http://www.artech.com/")]

   2: public interface ICalculator

   3: {

   4:     [WebInvoke(BodyStyle = WebMessageBodyStyle.Bare)]

   5:     double Add( double x,  double y);

   6: }

如上所示的是我们熟悉的计算服务的契约接口的定义。消息主体风格为Bare的操作方法Create具有两个输入参数(x和y),在对实现了该契约接口进行寄宿的时候就会抛出如下图所示的InvalidOperationException异常,提示“约定“ICalculator”的操作‘Add’指定要序列化多个请求正文参数,但没有任何包装元素。如果没有包装元素,至多可序列化一个正文参数。请删除多余的正文参数,或将 WebGetAttribute/WebInvokeAttribute 的 BodyStyle 属性设置为 Wrapped”。

六、Bare回复消息风格对单一输出的要求

由于回复参数是对返回值、引用参数和输出参数的封装,所以当操作方法具有引用参数或者输出参数时不能将回复消息的主体风格设置为Bare。

   1: [ServiceContract(Namespace = "http://www.artech.com/")]

   2: public interface ICalculator

   3: {    

   4:     [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest)]

   5:     void Add( double x,  double y, out double result);

   6: }

同样以计算服务契约为例,现在我们通过如上的方式以输出参数的形式返回加法运算的结果,并将应用在操作方法上的WebInvokeAttribute特性的BodyStyle属性设置为WrappedRequest,这意味着请求消息和回复消息分别采用Wrapped和Bare风格。当我们对实现了该契约接口的服务设施寄宿时会抛出下图所示的InvalidOperationException异常,并提示“约定‘ICalculator’的操作‘Add’至少指定一个响应正文参数不是操作的返回值。当 WebGetAttribute/WebInvokeAttribute 的 BodyStyle 属性设置为 Bare 时,只允许使用返回值。请删除多余的响应正文参数或将 BodyStyle 属性设置为 Wrapped”。

作者:Artech
出处:http://artech.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
 

[WCF REST] Web消息主体风格(Message Body Style)的更多相关文章

  1. Web消息主体风格(Message Body Style)

    对于Web HTTP编程模型来说,服务契约中作为操作的方法无须应用OperationContractAttribute特性,只需要根据需要应用WebGetAttribute与WebInvokeAttr ...

  2. WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化

    原文:WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化 [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制 ...

  3. C# 的 WCF文章 消息契约(Message Contract)在流(Stream )传输大文件中的应用

    我也遇到同样问题,所以抄下做MARK http://www.cnblogs.com/lmjq/archive/2011/07/19/2110319.html 刚做完一个binding为netTcpBi ...

  4. Web API中的消息处理程序(Message Handler)

    一.消息处理程序的概念 信息处理程序(Message Handler)接收HTTP请求并返回一个HTTP响应的类.Message Handler继承 HttpMessageHandler 类. 通常, ...

  5. WCF、Web API、WCF REST、Web Service比较

    原文地址:http://www.dotnet-tricks.com/Tutorial/webapi/JI2X050413-Difference-between-WCF-and-Web-API-and- ...

  6. Difference between WCF and Web API and WCF REST and Web Service

    The .Net framework has a number of technologies that allow you to create HTTP services such as Web S ...

  7. WCF 、Web API 、 WCF REST 和 Web Service 的区别

    WCF .Web API . WCF REST 和 Web Service 的区别 The .Net framework has a number of technologies that allow ...

  8. wcf和web service的区别

    1.WebService:严格来说是行业标准,不是技术,使用XML扩展标记语言来表示数据(这个是夸语言和平台的关键).微软的Web服务实现称为ASP.NET Web Service.它使用Soap简单 ...

  9. Azure开发者任务之六:使用WCF Service Web Role

    在本文中,我们将会在local development fabric上创建一个WCF服务角色,然后在一个控制台应用程序中使用它. WCF服务角色可以让我们创建一个WCF服务,并且把它托管在Window ...

随机推荐

  1. UNIX环境高级编程笔记之进程控制

    本章重点介绍了进程控制的几个函数:fork.exec族._exit.wait和waitpid等,主要需要掌握的是父进程和子进程之间的运行机制,怎么处理进程的正常和异常终止.以及怎么让进程执行不同的程序 ...

  2. LintCode-- Remove Linked List Elements

    Remove all elements from a linked list of integers that have valueval. 样例 Given 1->2->3->3- ...

  3. 图文安装Windows Template Library - WTL Version 9.0

    从http://wtl.sourceforge.net/下载 WTL 9.0,或者点此链接下载:WTL90_4140_Final.zip,然后解压到你的VC目录下面, 我的地址是:C:\Program ...

  4. linux下批量查找/替换文本内容

    一般在本地电脑上批量替换文本有许多工具可以做到,比如sublime text ,但大多服务器上都是无图形界面的,为此收集了几条针对linux命令行 实现批量替换文本内容的命令: 1.批量查找某个目下文 ...

  5. eclipse 手动/自动安装插件

    只要你的Eclipse的压缩包,一般为xxx.zip,其内部包含了对应的features和plugins文件夹,(不管是否还有content.jar和artifacts.jar)则都可以: 要么手动解 ...

  6. DDD:Repository和UnitOfWork的生命周期问题

    UnitOfWork UnitOfWork是一种有状态的.用例级别的对象.如果不采用ORM是不会使用UnitOfWork模式的, Repository Repository是一种特殊的领域服务,因此是 ...

  7. [mysql]brew 安装 配置 操作 mysql(中文问题)

    mac 下卸载mysqldmg mac下mysql的DMG格式安装内有安装文件,却没有卸载文件--很郁闷的事. 网上搜了一下,发现给的方法原来得手动去删. 很多文章记述要删的文件不完整,后来在stac ...

  8. Codeforces Round #313 (Div. 1) A. Gerald's Hexagon

    Gerald's Hexagon Problem's Link: http://codeforces.com/contest/559/problem/A Mean: 按顺时针顺序给出一个六边形的各边长 ...

  9. 利用mciSendString播放音频

    最近在写音频播放器,不过有点懒散,开发进度很慢,一天只做了一点点东西.其实就是让程序能播放音频.这个在我大二学winform程序开发时书上有说,那是书上教的是用media player的COM组件,而 ...

  10. 【C#进阶系列】05 基元类型、引用类型和值类型

     基元类型和FCL类型 FCL类型就是指Int32这种类型,这是CLR支持的类型. 而基元类型就是指int这种类型,这是C#编译器支持的,实际上在编译后,还是会被转为Int32类型. 而且学过C的朋友 ...