对于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”。

 
 

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

  1. [WCF REST] Web消息主体风格(Message Body Style)

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

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

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

  3. 实现web消息推送的技术和采用长轮询corundumstudio介绍

    实时消息的推送,PC端的推送技术可以使用socket建立一个长连接来实现.传统的web服务都是客户端发出请求,服务端给出响应.但是现在直观的要求是允许特定时间内在没有客户端发起请求的情况下服务端主动推 ...

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

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

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

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

  6. 消息队列(Message Queue)简介及其使用

    消息队列(Message Queue)简介及其使用 摘要:利用 MSMQ(Microsoft Message Queue),应用程序开发人员可以通过发送和接收消息方便地与应用程序进行快速可靠的通信.消 ...

  7. 微软消息队列-MicroSoft Message Queue(MSMQ)队列的C#使用

    目录 定义的接口 接口实现 建立队列工厂 写入队列 获取消息 什么是MSMQ Message Queuing(MSMQ) 是微软开发的消息中间件,可应用于程序内部或程序之间的异步通信.主要的机制是:消 ...

  8. HTTP的POST提交的四种常见消息主体格式

    HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS.GET.HEAD.POST.PUT.DELETE.TRACE.CONNECT 这几种.其中 POST 一般用来向服务端提交数据,本文 ...

  9. 编程风格(Coding Style)要求

    编程风格(Coding Style)要求2.1.1 文件(1) 每个模块(module)一般应存在于单独的源文件中,通常源文件名与所包含模块名相同.(2) 每个设计文件开头应包含如下注释内容:? 年份 ...

随机推荐

  1. iOS 完美解决 interactivePopGestureRecognizer 卡住的问题

    interactivePopGestureRecognizer是iOS7推出的解决VeiwController滑动后退的新功能,虽然很实用,但是坑也很多啊,用过的同学肯定知道问题在哪里,所以具体问题我 ...

  2. iOS 在制作framework时候对aggregate的配置

    # Sets the target folders and the final framework product.# 如果工程名称和Framework的Target名称不一样的话,要自定义FMKNA ...

  3. JSP入门&会话技术

    一.JSP    1.jsp技术        jsp是sun提供动态web资源开发技术.为了解决在Servlet中拼写html内容css.js内容十分不方便的问题,sun提供了这样一门技术.如果说S ...

  4. 开源项目go2o - golang版的o2o项目

    发一个github上唯一用golang实现的o2o项目 What's Go2o Golang combine simple o2o DDD domain-driven design realizati ...

  5. 【转】PaxosLease算法--2PC看Paxos选主

    原文请参考[[置顶] Paxos master选举--PaxosLease算法] 众所周知,为了避免Paxos算法的活锁问题,必须选举唯一的proposor.偏偏在Paxos原论文中,作者L. Lam ...

  6. MySQL数据库初识(二)

    8. 向数据表中插入数据记录(INSERT): 向数据表中插入数据记录有两种方法: 基本语法1:INSERT INTO 数据表 (字段名1,字段名2,字段名3……字段名n) VALUES (数据值1, ...

  7. TFS配置过程中的错误

    有些人在配置TFS的过程中会报出[以前的更新或安装需要重新启动操作系统.……]的错误,但会发现无论重启多次操作系统,再配置的时候依然会报这个错误,很是让人苦恼哦. 这个错误在安装SharePoint的 ...

  8. python collections,函数等笔记

    笔记 # -*- coding:utf-8 -*- #需求:一个列表里大于66的元素添加字典的第二个key k2里,小于66的添加第一个 key k1里 li = [1,2,3,4,5,6,67,7, ...

  9. Python开发之【用户登录锁定】

    用户登录验证,输入密码错误三次,锁定此用户. 将用户信息存入文件 文件内容格式如下: {','login_flag':True} {','login_flag':True} {','login_fla ...

  10. C++ new(3)

    转载自:http://www.builder.com.cn/2008/0104/696370.shtml “new”是C++的一个关键字,同时也是操作符.关于new的话题非常多,因为它确实比较复杂,也 ...