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”。
Web消息主体风格(Message Body Style)相关推荐
- WCF技术剖析之十八:消息契约(Message Contract)和基于消息契约的序列化
在本篇文章中,我们将讨论WCF四大契约(服务契约.数据契约.消息契约和错误契约)之一的消息契约(Message Contract).服务契约关注于对服务操作的描述,数据契约关注于对于数据结构和格式的描 ...
- WEB消息推送—GoEasy
web实时推送的技术在大多数项目里面都会用到,尤其是一些实时性要求高的项目,关于这方面的实现技术有许多,类似于webscoket.dwr.comet4j和netpush等等,其中在以往的篇幅里我也介绍 ...
- 纯js消息弹窗组件Message
js消息弹窗组件 文章目录 js消息弹窗组件 1. js部分代码 2.使用方法 3.演示效果 写组件上瘾,今天写一个纯js消息弹窗组件,复制即可使用,css也写在了js之中,用js生成,代码若是存在不 ...
- ElementUI 消息提示组件Message
目录 官方地址 应用场景 基本用法 通知类型 偏移量 使用HTML代码片段 开启关闭按钮 文字内容居中 自定义图标iconClass onClose close实例方法 全局引入 单独引用 Optio ...
- 吴恩达老师深度学习视频课笔记:神经风格迁移(neural style transfer)
什么是神经风格迁移(neural style transfer):如下图,Content为原始拍摄的图像,Style为一种风格图像.如果用Style来重新创造Content照片,神经风 ...
- 图像迁移风格保存模型_CV之NS:图像风格迁移(Neural Style 图像风格变换)算法简介、关键步骤配图、案例应用...
CV之NS:图像风格迁移(Neural Style 图像风格变换)算法简介.过程思路.关键步骤配图.案例应用之详细攻略 目录 图像风格迁移算法简介 图像风格迁移算法过程思路 1.VGG对比NS 图像风 ...
- JMS Java消息服务(Java Message Service)
JMS 在一些场景下RPC的同步方式可能不太适合业务逻辑的处理,并且这种方式在某些场景下会导致业务的紧耦合. 基于异步交互模型的JMS解决了RPC产生的紧耦合问题,它提供了一个可以通过网络访问的抽象消 ...
- CV之NS:图像风格迁移(Neural Style 图像风格变换)算法简介、过程思路、关键步骤配图、案例应用之详细攻略
CV之NS:图像风格迁移(Neural Style 图像风格变换)算法简介.过程思路.关键步骤配图.案例应用之详细攻略 目录 图像风格迁移算法简介 图像风格迁移算法过程思路 1.VGG对比NS 图像风 ...
- notes邮件正文显示不全_Outlook邮件中的可操作消息(Actionable Message)
邮件大家都不陌生,而且很可能它也是当前工作生活中应用最广的沟通方式之一了.据不完全统计,每月通过Office 365发送的邮件数量达到4700亿封. 近些年来,随着社会发展,逐渐有一个趋势就基于聊天( ...
最新文章
- 上传图片被防火墙拦截_Web安全:文件上传漏洞
- 韩顺平老师 Mysql优化 笔记
- 组件赋值——@Value ---@PropertySource(value={“classpath:/person.properties“})
- 《漫画算法2》源码整理-1 二分查找树 AVL树 红黑树
- 车提示检测轮胎气压_无钥匙启动的车启动后,车主带着钥匙离开车,能不能把车开走?...
- 查看php 相关信息
- 史上最简单的SpringCloud教程 | 第八篇: 消息总线(Spring Cloud Bus)
- 关于正点原子STM32的MDK例程移植到IAR中遇到的错误解决方法 __use_no_semihosting
- Java 8的默认方法:可以做什么和不能做什么?
- MySQL为什么要用数字做自增主键?
- 基于MM2的跨IDC kafka热备多活方案
- python输出para关键词占比_使用python操作word
- WebGL 绘制Line的bug(三)
- VB.NET连接SQL数据库
- 如何枚举系统的视音频采集设备
- 微信读书 《围城》笔记
- 如何在word编辑文本框,教程来啦,怎样在word编辑文本框
- 使用HBuilder制作一个简单的HTML5动漫网页——紫罗兰永恒花园动漫价绍网页 7页
- 自学PHP 环境搭建
- 关于Ajax的英雄联盟查询英雄案例
热门文章
- C语言实现方差variance计算(附完整源码)
- C语言一级指针(char *)易错模型分析
- mysql myisam 主从_MySQL的主从复制Replication之MyIsam和InnoDB数据复制发布
- 「Caffe」python版本caffe编译
- Nginx缓存引发的跨域惨案(转:https://www.baidu.com/home/news/data/newspage?nid=9966642810298490574n_type=0p_f)
- Scala声明变量、常用类型、条件表达式、块表达式、循环
- linux 修改IP, DNS 命令
- Linux用户和组管理,查看软件缓存,通过命令查看硬件信息(cpu,版本,序列号,内存,主板,内核等)
- 远程连接SQL Server2008的设置方式
- 处理时间_3_计算两个时间列工作日差值