WCF(Windows Communication Foundation) - WCF 4.0 新特性:简化配置(Simplified configuration) - 根据 baseAddresses 生成默认 endpoint;在应用程序的级别上指定默认的 Binding 配置和 Behavior 配置;不需要 .svc 的物理文件,而直接在 IIS 上托管 WCF 服务;标准终结点(Standard Endpoint) - 内置了 8 个已经定义好相关配置的标准终结点(分别为 mexEndpoint, announcementEndpoint, discoveryEndpoint, udpAnnouncementEndpoint, udpDiscoveryEndpoint, workflowControlEndpoint, webHttpEndpoint, webScriptEndpoint);通过标准终结点中的 webScriptEndpoint 来提供 ajax 服务;对 REST 服务支持的增强;对路由服务,工作流服务,字节流编码,非破坏性队列接收,服务发现的支持
介绍
WCF(Windows Communication Foundation) - WCF 4.0 新特性
- 简化配置(Simplified configuration) - 根据 baseAddresses 生成默认 endpoint;在应用程序的级别上指定默认的 Binding 配置和 Behavior 配置
- 不需要 .svc 的物理文件,而直接在 IIS 上托管 WCF 服务
- 标准终结点(Standard Endpoint) - 内置了 8 个已经定义好相关配置的标准终结点(分别为 mexEndpoint, announcementEndpoint, discoveryEndpoint, udpAnnouncementEndpoint, udpDiscoveryEndpoint, workflowControlEndpoint, webHttpEndpoint, webScriptEndpoint)
- 通过标准终结点中的 webScriptEndpoint 来提供 ajax 服务
- 对 REST 服务支持的增强
- 对路由服务,工作流服务,字节流编码,非破坏性队列接收,服务发现的支持
示例
1、概述
Index.aspx
代码 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="WebClient.Index" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<p>
1、简化配置(Simplified configuration) - 根据 baseAddresses 生成默认 endpoint;在应用程序的级别上指定默认的 Binding 配置和 Behavior 配置
<br />
相关代码位置:host 端在 WinHost 项目,client 端在 WebClient 项目中的 SimplifiedConfiguration.aspx 页面
</p>
<p>
2、不需要 .svc 的物理文件,而直接在 IIS 上托管 WCF 服务
<br />
相关代码位置:host 端在 WebHost 项目中的 web.config 文件,client 端在 WebClient 项目中的 IIS_Hosting_Without_SVC_File.aspx 页面
</p>
<p>
3、标准终结点(Standard Endpoint) - 内置了 8 个已经定义好相关配置的标准终结点(分别为 mexEndpoint, announcementEndpoint, discoveryEndpoint, udpAnnouncementEndpoint, udpDiscoveryEndpoint, workflowControlEndpoint, webHttpEndpoint, webScriptEndpoint)
<br />
指定标准终结点的方法见 WebHost 项目中的 web.config 文件
</p>
<p>
4、通过标准终结点中的 webScriptEndpoint 来提供 ajax 服务
<br />
相关代码位置:host 端在 WebHost 项目中的 web.config 文件,client 端在 WebHost 项目中的 WebScriptEndpointDemo.aspx 页面
</p>
<p>
5、对 REST 服务支持的增强
<ul>
<li>
通过标准终结点 webHttpEndpoint 来简化配置(详见:WebHost 项目中的 web.config 文件)
</li>
<li>
通过对 behavior 的配置来为 REST 服务增加 help 页面,在服务地址上加“/help”即可进入 REST 服务的帮助页面(详见:WebHost 项目中的 web.config 文件)
<br />
本例的 REST 服务的帮助页面为 http://localhost:14802/RestDemo.svc/help
</li>
<li>
为 REST 增加 HTTP 缓存配置(详见:WebHost 项目中的 web.config 文件,ServiceLib 项目的 RestDemo.cs 文件)
</li>
</ul>
</p>
<p>
6、路由服务(Routing Service) - WCF 对 Web Services Addressing (WS-Addressing) 规范的实现
</p>
<p>
7、工作流服务(Workflow Service) - WCF 对 WF (Workflow Foundation) 的支持
</p>
<p>
8、字节流编码(ByteStream) - 增加了对 ByteStream 的支持。原来只支持 Text, Binary, MTOM
</p>
<p>
9、非破坏性队列接收(Non-destructive queue receive) - 改进了原有的对 MSMQ(消息队列) 的支持
</p>
<p>
10、服务发现(WS-Discovery) - 对 WS-Discovery 协议的支持
</p>
</div>
</form>
</body>
</html>
2、简化配置(Simplified configuration)的 Demo
服务端:Demo.cs
代码 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace ServiceLib
{
[ServiceContract]
public interface IDemo
{
[OperationContract]
string Hello(string name);
}
public class Demo : IDemo
{
public string Hello(string name)
{
return "Hello: " + name;
}
}
}
宿主:App.config 代码 <?xml version="1.0"?>
<configuration>
<system.serviceModel>
<!--
1、如果没有显示配置 endpoint,那么 WCF 会根据 baseAddresses 生成一个默认 endpoint
2、如果显示配置了 endpoint,那么 WCF 在默认情况下不会根据 baseAddresses 生成默认 endpoint
3、如果需要强制为每个 baseAddresses 生成默认 endpoint,那么只要调用 ServiceHost.AddDefaultEndpoints() 方法即可(即使显示地指定 endpoint 也会生成默认的 endpoint)
本例生成的默认 endpoint 的配置如下:
A: http://localhost:1122/
B: basicHttpBinding
C: ServiceLib.IDemo
-->
<services>
<service name="ServiceLib.Demo">
<host>
<baseAddresses>
<add baseAddress="http://localhost:1122/"/>
</baseAddresses>
</host>
</service>
</services>
<!--
根据协议类型,指定其所对应的默认 Binding
-->
<protocolMapping>
<add scheme="http" binding="basicHttpBinding"/>
<add scheme="net.tcp" binding="netTcpBinding"/>
<add scheme="net.pipe" binding="netNamedPipeBinding"/>
<add scheme="net.msmq" binding="netMsmqBinding"/>
</protocolMapping>
<!--
WCF 应用程序的默认 Behavior 配置
-->
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<!--
WCF 应用程序的默认 Binding 配置
-->
<bindings>
<basicHttpBinding></basicHttpBinding>
<webHttpBinding></webHttpBinding>
<wsHttpBinding>
<binding>
<security mode="Message">
<transport clientCredentialType="None"></transport>
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
宿主:Form1.cs 代码 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace WinHost
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Load += new EventHandler(Form1_Load);
}
void Form1_Load(object sender, EventArgs e)
{
ServiceHost host = new ServiceHost(typeof(ServiceLib.Demo));
// 强制为每个 baseAddresses 生成默认 endpoint(即使显示地指定 endpoint 也会生成默认的 endpoint)
// host.AddDefaultEndpoints();
if (host.State != CommunicationState.Opening)
host.Open();
txtMsg.Text += string.Format("endpoint 的数量: {0}", host.Description.Endpoints.Count);
txtMsg.Text += "\r\n";
foreach (ServiceEndpoint se in host.Description.Endpoints)
{
txtMsg.Text += string.Format("A: {0}\r\nB: {1}\r\nC: {2}",
se.Address, se.Binding.Name, se.Contract.Name);
}
}
}
}
3、演示在没有 .svc 物理文件的情况下,直接在 IIS 上托管 WCF 服务
宿主的配置:Web.config 代码 <?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<!--
要实现“不需要 .svc 的物理文件,而直接在 IIS 上托管 WCF 服务”的功能,需要指定相对地址和服务类型之间的映射关系
relativeAddress - 向外提供服务的相对地址
service - 服务类型
factory - ajax 服务使用 System.ServiceModel.Activation.WebScriptServiceHostFactory , rest 服务使用 System.ServiceModel.Activation.WebServiceHostFactory
-->
<serviceHostingEnvironment>
<serviceActivations>
<add relativeAddress="IIS_Hosting_Without_SVC_File.svc" service="ServiceLib.Demo" />
</serviceActivations>
</serviceHostingEnvironment>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
4、演示如何通过标准终结点中的 webScriptEndpoint 来提供 ajax 服务
服务端:AjaxDemo.cs 代码 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace ServiceLib
{
[ServiceContract(Namespace = "WCF")]
public interface IAjaxDemo
{
[OperationContract]
string Hello(string name);
}
public class AjaxDemo : IAjaxDemo
{
public string Hello(string name)
{
return "Hello: " + name;
}
}
}
宿主的配置:Web.config 代码 <?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<serviceHostingEnvironment>
<serviceActivations>
<add relativeAddress="WebScriptEndpointDemo.svc" service="ServiceLib.AjaxDemo" factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" />
</serviceActivations>
</serviceHostingEnvironment>
<!--
标准终结点是已经定义好相关配置的标准终结点
通过 kind 指定标准终结点
-->
<services>
<service name="ServiceLib.AjaxDemo">
<endpoint kind="webScriptEndpoint" contract="ServiceLib.IAjaxDemo" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
客户端:WebScriptEndpointDemo.aspx 代码 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebScriptEndpointDemo.aspx.cs"
Inherits="WebHost.WebScriptEndpointDemo" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<!--
因为 ajax 要同域,所以此 ajax 演示的 client 端要和 host 端在一起
-->
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="WebScriptEndpointDemo.svc" />
</Services>
</asp:ScriptManager>
<script type="text/javascript">
function pageLoad() {
var proxy = new WCF.IAjaxDemo();
proxy.Hello("webabcd", onSuccess, onFailed);
}
function onSuccess(result) {
alert(result);
}
function onFailed(error) {
alert(error.get_message());
}
</script>
</div>
</form>
</body>
</html>
5、REST 服务的增强
服务端:RestDemo.cs 代码 /*
* 注意:
* 如果需要引用 System.ServiceModel.Web 程序集的话,需要把程序的目标框架设置为 .NET Framework 4 而不是默认的 .NET Framework 4 Client Profile(精简版)
* 引用了目标框架为 .NET Framework 4 的项目的程序的目标框架也应该是 .NET Framework 4
*/
/*
* 要在 REST 服务上实现 HTTP 缓存,需要做的配置如下
* 1、在 web.config 中的 system.web/caching 节点上为 REST 服务提供一个缓存配置
* 2、在方法上通过类似 [AspNetCacheProfile("Cache30S")] 的声明指定方法所使用的缓存配置
* 3、在 web.config 中的 system.serviceModel/serviceHostingEnvironment 节点上增加一个属性 aspNetCompatibilityEnabled="true" ,以启用 asp.net 兼容模式
* 4、在方法上使用如下声明,[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] ,以启用 asp.net 兼容模式
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Activation;
namespace ServiceLib
{
[ServiceContract]
public interface IRestDemo
{
[OperationContract]
[WebGet(UriTemplate = "Hello/{name}", ResponseFormat = WebMessageFormat.Json)]
[AspNetCacheProfile("Cache30S")]
string Hello(string name);
}
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class RestDemo : IRestDemo
{
public string Hello(string name)
{
return "Hello: " + name + " - " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
}
}
}
宿主端的配置:Web.config 代码 <?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<!--
要在 REST 服务上实现 HTTP 缓存,需要做的配置如下
1、在 web.config 中的 system.web/caching 节点上为 REST 服务提供一个缓存配置
2、在方法上通过类似 [AspNetCacheProfile("Cache30S")] 的声明指定方法所使用的缓存配置
3、在 web.config 中的 system.serviceModel/serviceHostingEnvironment 节点上增加一个属性 aspNetCompatibilityEnabled="true" ,以启用 asp.net 兼容模式
4、在方法上使用如下声明,[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] ,以启用 asp.net 兼容模式
-->
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="Cache30S" duration="30" varyByParam="*" />
</outputCacheProfiles>
</outputCacheSettings>
</caching>
</system.web>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true">
<serviceActivations>
<add relativeAddress="RestDemo.svc" service="ServiceLib.RestDemo" factory="System.ServiceModel.Activation.WebServiceHostFactory" />
</serviceActivations>
</serviceHostingEnvironment>
<!--
标准终结点是已经定义好相关配置的标准终结点
通过 kind 指定标准终结点
-->
<services>
<service name="ServiceLib.RestDemo">
<endpoint kind="webHttpEndpoint" contract="ServiceLib.IRestDemo" behaviorConfiguration="HelpBehavior" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<!--
启用 REST 的 Help 功能(在服务地址上加“/help”即可进入 REST 服务的帮助页面)
本例的 REST 服务的帮助页面为 http://localhost:14802/RestDemo.svc/help
-->
<behavior name="HelpBehavior">
<webHttp helpEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
客户端:RestDemo.aspx.cs 代码 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Net;
namespace WebClient
{
public partial class RestDemo : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
System.Net.WebClient client = new System.Net.WebClient();
var jsonResult = client.DownloadString("http://localhost:14802/RestDemo.svc/Hello/webabcd");
Response.Write(jsonResult);
}
}
}
OK