posts - 615, comments - 10488, trackbacks - 594, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

公告

化零为整WCF(19) - WCF 4.0 新特性

Posted on 2010-08-02 09:08 webabcd 阅读(...) 评论(...) 编辑 收藏
[索引页]
[源码下载]


化零为整WCF(19) - WCF 4.0 新特性


作者:webabcd


介绍
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
[源码下载]