【转】 在 ASP.NET 3.5 中使用同时支持 Ajax Json 和 .NET 客户端的 WCF 服务

 近期的开发要求使用 IIS 承载的 WCF 提供数据和实现操作,客户端使用 Ajax Json 和 WinForm,因此要在统一服务上同时绑定用于 Ajax 的 webHttpBinding 和用于 WinForm 的 wsHttpBinding。

  下面假定服务名为 Itoro.WebCore.Web。

  在创建服务时,选择“启用了 AJAX 的 WCF 服务”,然后在 web.config 会自动在 system.serviceModel 下生成相关配置,默认的用于 Ajax 的配置是行为中的名为 Itoro.WebCore.WebAspNetAjaxBehavior 的终点行为,并且使用 <enableWebScript /> 启用 Ajax Javascript 支持。在服务配置中是一个名为 Itoro.WebCore.Web 的服务,其中的终点配置为使用 Itoro.WebCore.WebAspNetAjaxBehavior 行为并绑定到 webHttpBanding。

  接下来是手动修改配置以支持 WinForm 的客户端访问,即 wsHttpBinding。

  在 system.serviceModel/behaviors/serviceBehaviors 下添加如下内容(如不存在 serviceBehaviors 则在相应位置创建该元素):

<behavior name="Itoro.WebCore.WebBehavior">
    
<serviceMetadata httpGetEnabled="true" />
</behavior>

  该配置指定名为 Itoro.WebCore.WebBehavior 的服务行为启用 Http 下的服务元数据。

  接下来修改名为 Itoro.WebCore.Web 的服务(即 <service name="Itoro.WebCore.Web" /> 元素)为以下内容:

<service behaviorConfiguration="Itoro.WebCore.WebBehavior" name="Itoro.WebCore.Web">
    
<endpoint address="web" behaviorConfiguration="Itoro.WebCore.WebAspNetAjaxBehavior"
        binding
="webHttpBinding" contract="Itoro.WebCore.Web" />
    
<endpoint address="ws" binding="wsHttpBinding" contract="Itoro.WebCore.Web">
        
<identity>
            
<dns value="localhost"/>
        
</identity>
    
</endpoint>
    
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>

  其中添加 service 元素中的 behaviorConfiguration,添加了2个终点配置,分别为用于 WinForm 的 wsHttpBinding 和用于元数据的 mexHttpBinding。另外,修改 webHttpBinding 和 wsHttpBinding 的 address 属性分别的 web 和 ws(也可以自定义,但是一定要设置,而且不能相同,否则会因为不同类型的绑定监听同一 Uri 而发生错误)。

  完整的配置如下:

<system.serviceModel>
    
<behaviors>
        
<endpointBehaviors>
            
<behavior name="Itoro.WebCore.WebAspNetAjaxBehavior">
                
<enableWebScript />
            
</behavior>
        
</endpointBehaviors>
        
<serviceBehaviors>
            
<behavior name="Itoro.WebCore.WebBehavior">
                
<serviceMetadata httpGetEnabled="true" />
            
</behavior>
        
</serviceBehaviors>
    
</behaviors>
    
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
    
<services>
        
<service behaviorConfiguration="Itoro.WebCore.WebBehavior" name="Itoro.WebCore.Web">
            
<endpoint address="web" behaviorConfiguration="Itoro.WebCore.WebAspNetAjaxBehavior"
                binding
="webHttpBinding" contract="Itoro.WebCore.Web" />
            
<endpoint address="ws" binding="wsHttpBinding" contract="Itoro.WebCore.Web">
                
<identity>
                    
<dns value="localhost"/>
                
</identity>
            
</endpoint>
            
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        
</service>
    
</services>
</system.serviceModel>

  最后在服务使用上也要有些变动,假设我们的服务为 http://localhost/Web.svc,那么在 Ajax 网站上添加服务时应该使用 Web.svc/web,而生成的脚本引用地址为 Web.svc/web/js,其中的 web 即为 webHttpBinding 中的 address。在 WinForm 中可以直接通过 http://localhost/Web.svc 添加服务引用,在生成的 app.config 中 /configuration/system.serviceModel/client 下会有2个终点配置,其中一个是 WebHttpBinding_Web,另外一个是 WSHttpBinding_Web,因此在使用时必须指定终点为 WSHttpBinding_Web,即 WebClient client = new WebClient("WSHttpBinding_Web") 否则运行时会出现错误。

  最后,因为 Web 是无状态的,而 WinForm 是有状态的,所以在 Web 下需要使用 Cookie(包括 Session),而在 WinForm 下只要 WebClient client 没有销毁就会一直保留同一状态,因为在编写服务的时候也要考虑兼容这两种模式。

posted @ 2008-09-06 08:47 DJ尐舞 阅读(...) 评论(...) 编辑 收藏