可以说WebHttpBinding和WebHttpBehavior是整个Web HTTP编程模型最为核心的两个类型,前者主要解决消息编码问题,而余下的工作基本上落在了终结点行为WebHttpBehavior上。WebHttpBehavior属性HelpEnabled和AutomaticFormatSelectionEnabled是“帮助页面”与“自动消息格式选择”这两个特性的总开关。[“自动消息格式(JSON/XML)选择”源代码从这里下载]

  1. 1: public class WebHttpBehavior : IEndpointBehavior, ...
  1. 2: {
  1. 3: //其他成员
  1. 4: public virtual bool HelpEnabled { get; set; }
  1. 5: public virtual bool AutomaticFormatSelectionEnabled { get; set; }
  1. 6: }

一、 帮助页面

WCF 4.0为REST服务提供了帮助页面功能,我们可以通过浏览器访问服务帮助页面的地址得到所有操作的基本信息。但是这个功能在默认的情况下是关闭的,我们需要通过应用在终结点上的WebHttpBehavior行为的HelpEnabled属性开启该功能。

  1. 1: <configuration>
  1. 2: <system.serviceModel>
  1. 3: <behaviors>
  1. 4: <endpointBehaviors>
  1. 5: <behavior>
  1. 6: <webHttp helpEnabled="true" />
  1. 7: </behavior>
  1. 8: </endpointBehaviors>
  1. 9: </behaviors>
  1. 10: <services>
  1. 11: <service name="Artech.WcfServices.Service.EmployeesService">
  1. 12: <endpoint address="http://127.0.0.1:3721/employees"
  1. 13: binding="webHttpBinding"
  1. 14: contract="Artech.WcfServices.Service.Interface.IEmployees"/>
  1. 15: </service>
  1. 16: </services>
  1. 17: </system.serviceModel>
  1. 18: </configuration>

同样以之前演示的EmployeesService为例,我们通过如上的配置将终结点行为WebHttpHehavior应用在服务唯一的终结点上(默认终结点),并将HelpEnabled属性设置为True。那么基于终结点的帮助页面将以地址{终结点地址}/Help发布出来,我们通过浏览器访问这个地址就会得到如下图所示帮助页面。

如上图所示,帮助页面列出了包括相对地址、HTTP方法和基本描述在内的所有操作的基本信息。我们通过点击HTTP方法对应的链接可以获得包括基于相应格式(Xml和Json)消息结构(Schema)和实例。在默认的情况下,帮助页面中表示操作描述信息的格式为“Service at {操作地址}”,我们可以在定义服务契约的时候再操作方法上应用特性DescriptionAttribute来定义出现在帮助页面中的描述信息。

  1. 1: [ServiceContract]
  1. 2: public interface IEmployees
  1. 3: {
  1. 4: [WebGet(UriTemplate = "all")]
  1. 5: [Description("获取所有员工列表")]
  1. 6: IEnumerable<Employee> GetAll();
  1. 7: 
  1. 8: [WebGet(UriTemplate = "{id}")]
  1. 9: [Description("获取指定ID的员工")]
  1. 10: Employee Get(string id);
  1. 11: 
  1. 12: [WebInvoke(UriTemplate = "/", Method = "POST")]
  1. 13: [Description("创建一个新的员工")]
  1. 14: Employee Create(Employee employee);
  1. 15: 
  1. 16: [WebInvoke(UriTemplate = "/", Method = "PUT")]
  1. 17: [Description("修改现有员工信息")]
  1. 18: void Update(Employee employee);
  1. 19: 
  1. 20: [WebInvoke(UriTemplate = "{id}", Method = "DELETE")]
  1. 21: [Description("删除指定ID的员工")]
  1. 22: void Delete(string id);
  1. 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. 1: <configuration>
  1. 2: <system.serviceModel>
  1. 3: <behaviors>
  1. 4: <endpointBehaviors>
  1. 5: <behavior name="webHttp">
  1. 6: <webHttp automaticFormatSelectionEnabled="true" />
  1. 7: </behavior>
  1. 8: </endpointBehaviors>
  1. 9: </behaviors>
  1. 10: <services>
  1. 11: <service name="Artech.WcfServices.Service.EmployeesService">
  1. 12: <endpoint address="http://127.0.0.1:3721/employees"
  1. 13: behaviorConfiguration="webHttp"
  1. 14: binding="webHttpBinding"
  1. 15: contract="Artech.WcfServices.Service.Interface.IEmployees"/>
  1. 16: </service>
  1. 17: </services>
  1. 18: </system.serviceModel>
  1. 19: </configuration>

对于契约接口IEmployees来说,我们通过WebGetAttribute特性用于返回所有员工列表的GetAll操作的回复消息格式设置为Xml。

  1. 1: [ServiceContract]
  1. 2: public interface IEmployees
  1. 3: {
  1. 4: //其他成员
  1. 5: [WebGet(UriTemplate = "all",ResponseFormat = WebMessageFormat.Xml)]
  1. 6: IEnumerable<Employee> GetAll();
  1. 7: }

对于REST服务调用来说,其本质就是一种普通的HTTP请求,与针对某个网页的访问并没有什么本质的不同,所以我们完全可以手工生成HTTP请求来进行服务的访问。为此我们创建了如下一个静态方法GetAllEmployees方法通过WebClient对服务的GetAll操作进行调用,并将整个回复消息打印出来,该方法的两个参数分别是作为请求的HTTP消息的Content-Type和Accept报头值。

  1. 1: static void GetAllEmployees(string contentType, string accept)
  1. 2: {
  1. 3: WebClient webClient = new WebClient();
  1. 4: if (!string.IsNullOrEmpty(contentType))
  1. 5: {
  1. 6: webClient.Headers.Add("Content-Type", contentType);
  1. 7: }
  1. 8: 
  1. 9: if (!string.IsNullOrEmpty(accept))
  1. 10: {
  1. 11: webClient.Headers.Add("Accept", accept);
  1. 12: }
  1. 13: using (StreamReader reader = new StreamReader(webClient.OpenRead(
  1. 14: "http://127.0.0.1:3721/employees/all")))
  1. 15: {
  1. 16: Console.WriteLine(reader.ReadToEnd());
  1. 17: }
  1. 18: }

然后我们通过调用GetAllEmployees方法进行三次服务调用。第一次调用既没有指定Content-Type报头也没有指定Accept报头,第二次和第三次调用在分别将这两个报头指定为“application/json”。

  1. 1: string contentType = "application/json";
  1. 2: 
  1. 3: Console.WriteLine("Content-Type = N/A; Accept = N/A:");
  1. 4: GetAllEmployees("", "");
  1. 5: Console.WriteLine();
  1. 6: 
  1. 7: Console.WriteLine("Content-Type = application/json; Accept = N/A:");
  1. 8: GetAllEmployees(contentType, "");
  1. 9: Console.WriteLine();
  1. 10: 
  1. 11: Console.WriteLine("Content-Type = N/A, Accept = application/json:");
  1. 12: GetAllEmployees("", contentType);

从如下所示的输出结果我们可以看出:由于服务调用请求没有指定任何媒体类型相关的报头,所以回复消息采用的是契约接口中设置的消息格式Xml。对于后两次服务调用中,由于请求消息中分别通过Content-Type和Accept报头将“期望”的媒体类型设置为application/json,所以Json最终作为回复消息的格式。(S1006)

  1. 1: Content-Type = N/A; Accept = N/A:
  1. 2: <ArrayOfEmployee xmlns="http://www.artech.com/" xmlns:i="http://www.w3.org/2001/
  1. 3: XMLSchema-instance"><Employee><Department>开发部</Department><Grade>G7</Grade><I
  1. 4: d>001</Id><Name>张三</Name></Employee><Employee><Department>人事部</Department><
  1. 5: Grade>G6</Grade><Id>002</Id><Name>李四</Name></Employee></ArrayOfEmployee>
  1. 6: 
  1. 7: Content-Type = application/json; Accept = N/A:
  1. 8: [{"Department":"开发部","Grade":"G7","Id":"001","Name":"张三"},{"Department":"人
  1. 9: 事部","Grade":"G6","Id":"002","Name":"李四"}]
  1. 10: 
  1. 11: Content-Type = N/A, Accept = application/json:
  1. 12: [{"Department":"开发部","Grade":"G7","Id":"001","Name":"张三"},{"Department":"人
  1. 13: 事部","Grade":"G6","Id":"002","Name":"李四"}]

【转】[WCF REST] 帮助页面与自动消息格式(JSON/XML)选择的更多相关文章

  1. WCF技术剖析之十七:消息(Message)详解(下篇)

    原文:WCF技术剖析之十七:消息(Message)详解(下篇) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制的节目视频(苏州话)]]< ...

  2. WCF技术剖析之十七:消息(Message)详解(中篇)

    原文:WCF技术剖析之十七:消息(Message)详解(中篇) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制的节目视频(苏州话)]]在上篇中 ...

  3. WCF技术剖析之十七:消息(Message)详解(上篇)

    原文:WCF技术剖析之十七:消息(Message)详解(上篇) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济频道<天天山海经>为此录制的节目视频(苏州话)]]消息交换 ...

  4. 当滚动条滚动到页面底部自动加载增加内容的js代码

    这篇文章主要介绍了如何使用javscript实现滚动条滚动到页面底部自动加载增加页面内容,需要的朋友可以参考下..1,注册页面滚动事件,window.onscroll = function(){ }; ...

  5. JSP页面实现自动跳转

    1 <html><head><script language=javascript> function out(obj) {  var i = obj;  if ( ...

  6. JSP页面实现自动跳转!

    JSP页面实现自动跳转!一.页面自动刷新: 把如下代码加入<head>区域中<meta http-equiv=”refresh” content=”5″>注:content=” ...

  7. Android借助Handler,实现ViewPager中页面的自动切换(转)

    在很多电商网页及app上都有自动切换的商品的推广快,感觉体验挺不错的,正好今天学习使用ViewPager,因此也实现了一个功能类似的demo. 下面是其中的两个截图:           实现一个自动 ...

  8. Js 在页面中输入消息的几种方式

    一.方式 alert(“”); confirm(“”) ; prompt(“”);         接收用户信息 console.log(“”);      在网页控制台中输出消息 document. ...

  9. 解决Intellij Idea下修改jsp页面不自动更新

    解决Intellij Idea下修改jsp页面不自动更新 On frame deactivation:被设置成了Do nothing 解决办法:改为Update resources(更新资源)或者Up ...

随机推荐

  1. c#中var关键字用法

    Technorati 标签: C# 转载自csdn:http://blog.csdn.net/robingaoxb/article/details/6175533   var关键字是C# 3.0开始新 ...

  2. 查看oracle 启动了多久

    想看一下系统正常运行了多少天?开机多长时间没有重启了? windows系统 C:\>systeminfo |find “系统启动时间”系统启动时间:     265 天 4 小时 26 分 32 ...

  3. 计算从A地出发到各个地方的路径及距离

    数据库环境:SQL SERVER 2005 如题,现有bus表数据如下,dstart是起点,dend是终点,distance是两地的距离.

  4. Java设计模式(学习整理)---适配模式

    设计模式之Adapter(适配器) 1.定义: 将两个不兼容的类纠合在一起使用,属于结构型模式,需要有Adaptee(被适配者)和Adaptor(适配器)两个身份. 2.为何使用? 我们经常碰到要将两 ...

  5. Apache提示You don't have permission to access / on this server问题解决

    测试时遇到将一本地目录设置为一apache的虚拟主机,在httpd-vhosts.conf文件中进行简单设置,然后在hosts文件中将访问地址指向本地,启动apache,进行访问,却出现了You do ...

  6. PHP的类自动加载机制

    在PHP开发过程中,如果希望从外部引入一个class,通常会使用include和require方法,去把定义这个class的文件包含进来. 这个在小规模开发的时候,没什么大问题.但在大型的开发项目中, ...

  7. WPF Window异形窗口演示

    我们先通过简单的效果展示,切换展示不同图片: 我们先定义图片资源文件,我们可以在window资源中定义,下面的在app.xaml文件来定义: <Application x:Class=" ...

  8. 简单学C——第七天

    函数 函数是C语言重要的组成部分,你现在,或者以后(如果C没什么变化的话)所写的任何一个C语言程序都是由一个一个的函数组合在一起的,当然,现在或许你只会在主函数 main中写一个小程序,那么在看了本篇 ...

  9. wndows 7 Wifi热点

    2016年09月13日 14時52分 wanglinqiang整理 Step1 cmd.exe(管理员身份运行) Step2 命令行输入[netsh wlan set hostednetwork mo ...

  10. matlab函数之bsxfun

    bsxfun(fun,A,B) 偶然间发现了这个函数,强大得不得了呀,它的作用是:对两个矩阵A和B之间的每一个元素进行指定的计算(函数fun指定):并且具有自动扩维的作用 例如,A是一个4*3的矩阵, ...