[WCF REST] WebServiceHost有何特别之处?
WCF为REST服务的寄宿提供了一个新的ServiceHost,即WebServiceHost。WebServiceHost是ServiceHost的子类,而WebServiceHostFactory是对应的ServiceHostFactory,在基于IIS/WAS寄宿中被使用。由于对REST服务绝大部分功能的支持都是通过WebHttpBehavior这么一个终结点行为实现的,所以WebServiceHost的核心功能就是将该终结点行为应用到寄宿服务的所有终结点。除此之外,WebServiceHost还具有一些额外的功能,这些功能都是通过重写OnOpening方法实现的。
一、ServiceDebugBehavior与ServiceMetadataBehavior
由于WebHttpBehavior提供了帮助页面,所以当我们通过WebServiceHost对REST服务进行寄宿的时候会屏蔽掉通过ServiceDebugBehavior服务行为提供的帮助页面。由于通过服务行为ServiceMetadataBehavior实现的元数据发布机制是基于SOAP的,如果我们在寄宿服务上应用了ServiceMetadataBehavior行为,WebServiceHost也会将基于HTTP-GET的元数据发布功能屏蔽。我们可以通过一个简单的实例来证实这一点。
1: using (WebServiceHost host = new WebServiceHost(typeof(EmployeesService)))
2: {
3: ServiceDebugBehavior serviceDebug =
4: host.Description.Behaviors.Find<ServiceDebugBehavior>();
5: if (null == serviceDebug)
6: {
7: serviceDebug = new ServiceDebugBehavior();
8: host.Description.Behaviors.Add(serviceDebug);
9: }
10: serviceDebug.HttpHelpPageEnabled = true;
11: serviceDebug.HttpsHelpPageEnabled = true;
12:
13: ServiceMetadataBehavior serviceMetadata =
14: host.Description.Behaviors.Find<ServiceMetadataBehavior>();
15: if (null == serviceMetadata)
16: {
17: serviceMetadata = new ServiceMetadataBehavior();
18: host.Description.Behaviors.Add(serviceMetadata);
19: }
20: serviceMetadata.HttpGetEnabled = true;
21: serviceMetadata.HttpsGetEnabled = true;
22: host.Open();
23:
24: Console.WriteLine("ServiceDebugBehavior");
25: Console.WriteLine("t{0, -20}: {1}", "HttpHelpPageEnabled", serviceDebug.HttpHelpPageEnabled);
26: Console.WriteLine("t{0, -20}: {1}n", "HttpsHelpPageEnabled", serviceDebug.HttpsHelpPageEnabled);
27:
28: Console.WriteLine("ServiceMetadataBehavior");
29: Console.WriteLine("t{0, -20}: {1}", "HttpGetEnabled", serviceMetadata.HttpGetEnabled);
30: Console.WriteLine("t{0, -20}: {1}", "HttpsGetEnabled", serviceMetadata.HttpsGetEnabled);
31: }
在如上所示的代码片断中,我们分别将服务行为ServiceDebugBehavior和ServiceMetadataBehavior应用在寄宿服务上,并将其HttpHelpPageEnabled/HttpsHelpPageEnabled和HttpGetEnabled/HttpsGetEnabled属性设置为True。在开启WebServiceHost之后我们将两个服务行为的这4个属性打印出来。从如下所示的输出结果我们可以看出这四个属性最终被设置成了False。
1: ServiceDebugBehavior
2: HttpHelpPageEnabled : False
3: HttpsHelpPageEnabled: False
4:
5: ServiceMetadataBehavior
6: HttpGetEnabled : False
7: HttpsGetEnabled : False
二、添加标准终结点
终结点是由地址、绑定和契约三要素构成,所谓标准终结点,就是基于典型的通信场景选择组成终结点的要素(主要是绑定和契约)进而创建出一个标准的终结点。如果我们在使用WebServiceHost进行服务寄宿的时候指定一个基地址,在没有添加任何终结点的情况下WebServiceHost会在开启过程中自动添加一个类型(Kind)为webHttpEndpoint 的标准终结点。我们同样可以通过实例演示来证实这一点。
1: Uri baseAddress = new Uri("http://127.0.0.1:3721/employees");
2: using (WebServiceHost host =
3: new WebServiceHost(typeof(EmployeesService), baseAddress))
4: {
5: host.Open();
6: ServiceEndpoint endpoinit = host.Description.Endpoints[0];
7: Console.WriteLine("{0,-8}: {1}", "Address", endpoinit.Address);
8: Console.WriteLine("{0,-8}: {1}", "Binding", endpoinit.Binding);
9: Console.WriteLine("{0,-8}: {1}", "Contract", endpoinit.Contract.ContractType);
10: }
在没有提供任何配置的情况下,我们通过如上的代码借助于WebServiceHost进行服务寄宿。在基于服务类型创建的WebServiceHost中指定了一个基地址,并在开启WebServiceHost之后,我们获取第一个终结点并将其三要素打印出来。从如下所示的输出结果我们可以看出:WebServiceHost基于服务类型实现的契约接口IEmployees创建了一个终结点,该终结点采用指定的基地址作为其地址,绑定类型为WebHttpBinding。
1: Address : http://127.0.0.1:3721/employees
2: Binding : System.ServiceModel.WebHttpBinding
3: Contract: Artech.WcfServices.Service.Interface.IEmployees
三、添加WebHttpBehavior终结点行为
正如上面所说,WebServiceHost除了完成从ServiceHost继承下来的服务寄宿功能之外,其只要的职责就是将WebHttpBehavior行为应用到寄宿服务的所有终结点上。也就是说,当我们开启WebServiceHost的时候,如果终结点没有应用WebHttpBehavior行为,会自动创建一个新的WebHttpBehavior对象应用到终结点上。WebHttpBehavior的自动添加可以通过如下代码中的调试断言来体现。
1: using (WebServiceHost host = new WebServiceHost(typeof(EmployeesService)))
2: {
3: foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
4: {
5: WebHttpBehavior behavior = endpoint.Behaviors.Find<WebHttpBehavior>();
6: if (null != behavior)
7: {
8: endpoint.Behaviors.Remove(behavior);
9: }
10: }
11: host.Open();
12: foreach (ServiceEndpoint endpoint in host.Description.Endpoints)
13: {
14: Debug.Assert(null != endpoint.Behaviors.Find<WebHttpBehavior>());
15: }
16: }
- 报警系统QuickAlarm之报警规则的设定与加载
- 报警系统QuickAlarm之报警执行器的设计与实现
- 如何在Kerberos与非Kerberos的CDH集群BDR不可用时复制数据
- 一个可扩展的报警系统Quick-Alarm
- 如何借助GitHub搭建属于自己的maven仓库
- Java可以如何实现文件变动的监听
- 如何在CDH中安装Kudu&Spark2&Kafka
- 秒懂 javascript 拖拽上传文件
- 一款轻量级树形控件EasyTreeview
- 大白话谈 Git
- 打造一个属于自己的 server
- 一款不可多得的火柴时钟
- 常见端口转发工具的使用方式(二)
- 如何在CDH启用Kerberos的情况下安装及使用Sentry(一)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- python第二十九课——文件读写(读取读取中文字符)
- python第二十九课——文件读写(readline()和readlines()的使用)
- linux系统运维企业常见面试题集合(一)
- python第二十九课——文件读写(写数据的操作)
- python第二十九课——文件读写(复制文件)
- python第三十课--异常(异常处理定义格式和常见类型)
- python第三十课--异常(finally讲解)
- python第三十课--异常(else讲解)
- Linux系统——shell脚本编程基础介绍
- python第三十课--异常(raise关键字)
- python第三十课--异常(异常对象传递过程)
- python第三十课--异常(with as操作)
- linux系统运维企业常见面试题集合(二)
- Linux系统Shell编程—企业生产案例(一)
- python第三十一课--递归(1.简单递归函数的定义和使用)