[WCF REST] Web消息主体风格(Message Body Style)
对于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”。
出处:http://artech.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
[WCF REST] Web消息主体风格(Message Body Style)的更多相关文章
- Web消息主体风格(Message Body Style)
对于Web HTTP编程模型来说,服务契约中作为操作的方法无须应用OperationContractAttribute特性,只需要根据需要应用WebGetAttribute与WebInvokeAttr ...
- WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化
原文:WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化 [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制 ...
- C# 的 WCF文章 消息契约(Message Contract)在流(Stream )传输大文件中的应用
我也遇到同样问题,所以抄下做MARK http://www.cnblogs.com/lmjq/archive/2011/07/19/2110319.html 刚做完一个binding为netTcpBi ...
- Web API中的消息处理程序(Message Handler)
一.消息处理程序的概念 信息处理程序(Message Handler)接收HTTP请求并返回一个HTTP响应的类.Message Handler继承 HttpMessageHandler 类. 通常, ...
- WCF、Web API、WCF REST、Web Service比较
原文地址:http://www.dotnet-tricks.com/Tutorial/webapi/JI2X050413-Difference-between-WCF-and-Web-API-and- ...
- 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 ...
- WCF 、Web API 、 WCF REST 和 Web Service 的区别
WCF .Web API . WCF REST 和 Web Service 的区别 The .Net framework has a number of technologies that allow ...
- wcf和web service的区别
1.WebService:严格来说是行业标准,不是技术,使用XML扩展标记语言来表示数据(这个是夸语言和平台的关键).微软的Web服务实现称为ASP.NET Web Service.它使用Soap简单 ...
- Azure开发者任务之六:使用WCF Service Web Role
在本文中,我们将会在local development fabric上创建一个WCF服务角色,然后在一个控制台应用程序中使用它. WCF服务角色可以让我们创建一个WCF服务,并且把它托管在Window ...
随机推荐
- Visual Studio 2013开启JavaScript的智能提示功能
在前一次的发布的时候,我们共享了Visual Studio 2013中Windows Azure移动服务的集成和功能.其中包含了移动服务表脚本的编辑能力的介绍.这一次的发布,我们将描述在Visual ...
- oracle 查询当前库中所有表以及某表字段信息
select utc.COLUMN_ID,utc.TABLE_NAME,utc.COLUMN_NAME,utc.DATA_TYPE||utc.DATA_LENGTH,utc.DATA_DEFAULT, ...
- 开发BI系统时的需求分析研究
我们知道MIS,知道ERP,知道GIS等等,这些系统在管理限制上有很多的冲突,管理和被管理,开放和限制等等,然而BI在开始就不是这样的.BI要求的就是易用还要易于扩展,首先是报表,这个是你无条件的需要 ...
- ruby 中文字符to_json后乱码(unicode)
今天遇到一个中文to_json问题 text = "第1章 青豆 不要被外表骗了" text.to_json => "\"\\u7b2c1\\u7ae0 ...
- php 使用zendstudio 生成webservice文件 wsdl
首先新建一个项目 在项目中新建下面这些文件 php类文件 test.php <?php class test { public function __construct() { } public ...
- 当应用程序不是以 UserInteractive 模式运行时显示模式对话框或窗体是无效操作
在Web程序中引用了WinForm的类库引起了 主要是为了在web程序中使用Message.Show()以及SaveFileDialog类,能web程序中引用了WinForm类库 在Visual St ...
- css3 keyframes在yuicompressor下压缩问题
@keyframes proBackAction { 0% { opacity:; } 100% { opacity: .8; } } @keyframes proBackAction { 0{ op ...
- Nginx: could not build the server_names_hash 解决办法
# /etc/init.d/nginx reload * Reloading nginx configuration nginx [fail] # nginx -t nginx: [emerg] co ...
- 值得拥有!精心推荐几款超实用的 CSS 开发工具
当你开发一个网站或 Web 应用程序的时候,有合适的工具,绝对可以帮助您节省大量的时间.在这篇文章中,我为大家收集了超有用的 CSS 开发工具. 对于 Web 开发人员来说,找到有用的 CSS 开发工 ...
- Configuring Service Broker for Asynchronous Processing
Configuring Service Broker for Asynchronous Processing --create a database and enable the database f ...