【转】[WCF REST] 帮助页面与自动消息格式(JSON/XML)选择
可以说WebHttpBinding和WebHttpBehavior是整个Web HTTP编程模型最为核心的两个类型,前者主要解决消息编码问题,而余下的工作基本上落在了终结点行为WebHttpBehavior上。WebHttpBehavior属性HelpEnabled和AutomaticFormatSelectionEnabled是“帮助页面”与“自动消息格式选择”这两个特性的总开关。[“自动消息格式(JSON/XML)选择”源代码从这里下载]
1: public class WebHttpBehavior : IEndpointBehavior, ...
2: {
3: //其他成员
4: public virtual bool HelpEnabled { get; set; }
5: public virtual bool AutomaticFormatSelectionEnabled { get; set; }
6: }
一、 帮助页面
WCF 4.0为REST服务提供了帮助页面功能,我们可以通过浏览器访问服务帮助页面的地址得到所有操作的基本信息。但是这个功能在默认的情况下是关闭的,我们需要通过应用在终结点上的WebHttpBehavior行为的HelpEnabled属性开启该功能。
1: <configuration>
2: <system.serviceModel>
3: <behaviors>
4: <endpointBehaviors>
5: <behavior>
6: <webHttp helpEnabled="true" />
7: </behavior>
8: </endpointBehaviors>
9: </behaviors>
10: <services>
11: <service name="Artech.WcfServices.Service.EmployeesService">
12: <endpoint address="http://127.0.0.1:3721/employees"
13: binding="webHttpBinding"
14: contract="Artech.WcfServices.Service.Interface.IEmployees"/>
15: </service>
16: </services>
17: </system.serviceModel>
18: </configuration>
同样以之前演示的EmployeesService为例,我们通过如上的配置将终结点行为WebHttpHehavior应用在服务唯一的终结点上(默认终结点),并将HelpEnabled属性设置为True。那么基于终结点的帮助页面将以地址{终结点地址}/Help发布出来,我们通过浏览器访问这个地址就会得到如下图所示帮助页面。

如上图所示,帮助页面列出了包括相对地址、HTTP方法和基本描述在内的所有操作的基本信息。我们通过点击HTTP方法对应的链接可以获得包括基于相应格式(Xml和Json)消息结构(Schema)和实例。在默认的情况下,帮助页面中表示操作描述信息的格式为“Service at {操作地址}”,我们可以在定义服务契约的时候再操作方法上应用特性DescriptionAttribute来定义出现在帮助页面中的描述信息。
1: [ServiceContract]
2: public interface IEmployees
3: {
4: [WebGet(UriTemplate = "all")]
5: [Description("获取所有员工列表")]
6: IEnumerable<Employee> GetAll();
7:
8: [WebGet(UriTemplate = "{id}")]
9: [Description("获取指定ID的员工")]
10: Employee Get(string id);
11:
12: [WebInvoke(UriTemplate = "/", Method = "POST")]
13: [Description("创建一个新的员工")]
14: Employee Create(Employee employee);
15:
16: [WebInvoke(UriTemplate = "/", Method = "PUT")]
17: [Description("修改现有员工信息")]
18: void Update(Employee employee);
19:
20: [WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
21: [Description("删除指定ID的员工")]
22: void Delete(string id);
23: }
如上面的代码片断所示,我们在契约接口IEmployees中的所有操作方法上应用了DescriptionAttribute特性并指定了相应的描述信息。这些描述信息就是出现在如下图所示的帮助页面中。

二、 自动消息格式选择
REST服务具有两种基本的消息格式(Xml和Json)。在定义服务契约的时候,我们可以通过应用在操作方法上的WebGetAttribute和WebInvokeAttribute指定回复消息的格式。如果没有通过这种方式对消息格式进行显式设置,我们还可以通过终结点行为WebHttpBehavior为回复消息设置一个默认的消息格式。除了这种显示设置方式之外,WCF还提供一种自动消息格式选择机制。
所谓消息格式的自动选择,就是服务根据请求消息来选择一种适合的格式进行消息的序列化。在默认的情况下,这种自动选择机制是关闭的,我们需要通过WebHttpBehavior的AutomaticFormatSelectionEnabled属性开启该机制。具体的消息格式选择机制策略(顺序)如下:
- 如果作为请求的HTTP消息具有Accept报头,则根据该报头决定回复消息的格式;
- 如果作为请求的HTTP消息具有Content-Type报头,则根据该报头决定回复消息的格式;
- 如果在定义服务契约时通过WebGetAttribute或者WebInvokeAttribute对回复消息的格式进行了显式设置,则采用该消息格式;
- 如果通过终结点行为WebHttpBehavior设置了对回复消息的格式进行了显式设置,则采用该消息格式;
- 采用默认消息格式Xml(WebMessageFormat枚举的默认值)。
我们同样通过之前创建的EmployeesService的实例来演示消息格式的自动选择机制。如下面的配置片断所示,我们将WebHttpBehavior行为应用到了寄宿服务的唯一终结点上,并且将AutomaticFormatSelectionEnabled属性设置为True。
1: <configuration>
2: <system.serviceModel>
3: <behaviors>
4: <endpointBehaviors>
5: <behavior name="webHttp">
6: <webHttp automaticFormatSelectionEnabled="true" />
7: </behavior>
8: </endpointBehaviors>
9: </behaviors>
10: <services>
11: <service name="Artech.WcfServices.Service.EmployeesService">
12: <endpoint address="http://127.0.0.1:3721/employees"
13: behaviorConfiguration="webHttp"
14: binding="webHttpBinding"
15: contract="Artech.WcfServices.Service.Interface.IEmployees"/>
16: </service>
17: </services>
18: </system.serviceModel>
19: </configuration>
对于契约接口IEmployees来说,我们通过WebGetAttribute特性用于返回所有员工列表的GetAll操作的回复消息格式设置为Xml。
1: [ServiceContract]
2: public interface IEmployees
3: {
4: //其他成员
5: [WebGet(UriTemplate = "all",ResponseFormat = WebMessageFormat.Xml)]
6: IEnumerable<Employee> GetAll();
7: }
对于REST服务调用来说,其本质就是一种普通的HTTP请求,与针对某个网页的访问并没有什么本质的不同,所以我们完全可以手工生成HTTP请求来进行服务的访问。为此我们创建了如下一个静态方法GetAllEmployees方法通过WebClient对服务的GetAll操作进行调用,并将整个回复消息打印出来,该方法的两个参数分别是作为请求的HTTP消息的Content-Type和Accept报头值。
1: static void GetAllEmployees(string contentType, string accept)
2: {
3: WebClient webClient = new WebClient();
4: if (!string.IsNullOrEmpty(contentType))
5: {
6: webClient.Headers.Add("Content-Type", contentType);
7: }
8:
9: if (!string.IsNullOrEmpty(accept))
10: {
11: webClient.Headers.Add("Accept", accept);
12: }
13: using (StreamReader reader = new StreamReader(webClient.OpenRead(
14: "http://127.0.0.1:3721/employees/all")))
15: {
16: Console.WriteLine(reader.ReadToEnd());
17: }
18: }
然后我们通过调用GetAllEmployees方法进行三次服务调用。第一次调用既没有指定Content-Type报头也没有指定Accept报头,第二次和第三次调用在分别将这两个报头指定为“application/json”。
1: string contentType = "application/json";
2:
3: Console.WriteLine("Content-Type = N/A; Accept = N/A:");
4: GetAllEmployees("", "");
5: Console.WriteLine();
6:
7: Console.WriteLine("Content-Type = application/json; Accept = N/A:");
8: GetAllEmployees(contentType, "");
9: Console.WriteLine();
10:
11: Console.WriteLine("Content-Type = N/A, Accept = application/json:");
12: GetAllEmployees("", contentType);
从如下所示的输出结果我们可以看出:由于服务调用请求没有指定任何媒体类型相关的报头,所以回复消息采用的是契约接口中设置的消息格式Xml。对于后两次服务调用中,由于请求消息中分别通过Content-Type和Accept报头将“期望”的媒体类型设置为application/json,所以Json最终作为回复消息的格式。(S1006)
1: Content-Type = N/A; Accept = N/A:
2: <ArrayOfEmployee xmlns="http://www.artech.com/" xmlns:i="http://www.w3.org/2001/
3: XMLSchema-instance"><Employee><Department>开发部</Department><Grade>G7</Grade><I
4: d>001</Id><Name>张三</Name></Employee><Employee><Department>人事部</Department><
5: Grade>G6</Grade><Id>002</Id><Name>李四</Name></Employee></ArrayOfEmployee>
6:
7: Content-Type = application/json; Accept = N/A:
8: [{"Department":"开发部","Grade":"G7","Id":"001","Name":"张三"},{"Department":"人
9: 事部","Grade":"G6","Id":"002","Name":"李四"}]
10:
11: Content-Type = N/A, Accept = application/json:
12: [{"Department":"开发部","Grade":"G7","Id":"001","Name":"张三"},{"Department":"人
13: 事部","Grade":"G6","Id":"002","Name":"李四"}]
【转】[WCF REST] 帮助页面与自动消息格式(JSON/XML)选择的更多相关文章
- WCF技术剖析之十七:消息(Message)详解(下篇)
原文:WCF技术剖析之十七:消息(Message)详解(下篇) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制的节目视频(苏州话)]]< ...
- WCF技术剖析之十七:消息(Message)详解(中篇)
原文:WCF技术剖析之十七:消息(Message)详解(中篇) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制的节目视频(苏州话)]]在上篇中 ...
- WCF技术剖析之十七:消息(Message)详解(上篇)
原文:WCF技术剖析之十七:消息(Message)详解(上篇) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制的节目视频(苏州话)]]消息交换 ...
- 当滚动条滚动到页面底部自动加载增加内容的js代码
这篇文章主要介绍了如何使用javscript实现滚动条滚动到页面底部自动加载增加页面内容,需要的朋友可以参考下..1,注册页面滚动事件,window.onscroll = function(){ }; ...
- JSP页面实现自动跳转
1 <html><head><script language=javascript> function out(obj) { var i = obj; if ( ...
- JSP页面实现自动跳转!
JSP页面实现自动跳转!一.页面自动刷新: 把如下代码加入<head>区域中<meta http-equiv=”refresh” content=”5″>注:content=” ...
- Android借助Handler,实现ViewPager中页面的自动切换(转)
在很多电商网页及app上都有自动切换的商品的推广快,感觉体验挺不错的,正好今天学习使用ViewPager,因此也实现了一个功能类似的demo. 下面是其中的两个截图: 实现一个自动 ...
- Js 在页面中输入消息的几种方式
一.方式 alert(“”); confirm(“”) ; prompt(“”); 接收用户信息 console.log(“”); 在网页控制台中输出消息 document. ...
- 解决Intellij Idea下修改jsp页面不自动更新
解决Intellij Idea下修改jsp页面不自动更新 On frame deactivation:被设置成了Do nothing 解决办法:改为Update resources(更新资源)或者Up ...
随机推荐
- webrtc学习———记录一
最近导师让研究一下webrtc,希望将来用到我们的ICT2系统中. 但是从来没有过做web的基础,无论前端还是后端,html.js全都从头学起.html还好说,没有太过复杂的东西. js就有点难度了, ...
- DataGrid列的合并
/// <summary> /// DataGrid列的合并 /// 注意:1.DataGrid在绑定的时候进行分组和排序,才能让相同的行放在一起 /// 2.方法应用的时机,应该在Dat ...
- 快速消除IOS 版本升级带来的警告
开发中我们经常会遇到这样的情况,我们在IOS 6.0开发的程序,当出现IOS 7.0 或者IOS8.0的时候,我们代码中得某些方法苹果已经不推荐使用了,建议我们改用新的方法.如果我们不更新方法,则会出 ...
- log4j文件
log4j文件是一种开源日志记录工具,其作用是记录程序运异常行过程中的重要的操作信息和记录可能出现的异常情况便于调试. 根据日志记录的信息内容可分为3类: Sql日志:记录系统执行的SQL语句 异常日 ...
- 简单的完全背包HDU1114
今天广州下雨啦,不过没关系啦,反正我最近也都在刷题学习算法. 昨天做了五题01背包,今天还是背包,不过是完全背包,估计做动态规划要持续好一段时间,一开始选了一道简单题目啦. HDU1114,看了小一段 ...
- C++的显示转换
利用显示转换使得我们可以很容易发现它们,因为通过名字就能找到: static_cast 用于“良性”和“适度良性”转换,包括不用强制转换 const_cast 对“const”和“volatil ...
- [Lua]索引极致,form.lua
local form = {_tag = 'form'} function form.build(tag, super) local target = { _tag = tag, _super = s ...
- javascript 获取 class 样式 重新赋值class样式 为div等系列标签内更改内容
name = document.getElementById(project_not_through_id).className; // 获取目标id的 cla ...
- 修改虚拟机linux硬盘的大小
一.概述 Ubuntu用了一段时间,系统已从原来的4G增长到8G,导致虚拟磁盘不够用,需要修改虚拟硬盘的大小. 但是,修改虚拟机硬盘的大小不像修改内存那么简单,操作一个滑动条就轻松搞定.要知道虚拟硬盘 ...
- ASP.NET MVC轻教程 Step By Step 6——改进表单
上一节我们使用原始的HTML表单来完成留言功能,但是ASP.NET MVC提供了丰富的HTML辅助方法来帮助我们构建更简洁优雅的表单. Step 1. 修改Form标签 首先,我们可以使用Html.B ...