• 关于WCF的一个非常“无语”的BUG!


    这确实是一个让人觉得“无语”的BUG,甚至让我觉得微软在故意和我们开玩笑。这个问题在我刚刚接触WCF的时候就遇到过,换言之,这个问题一直存在于.NET 3.0、3.5和现在的4.0。这是一个关于在你对WCF进行扩展的时候会经常碰到的问题,读者朋友们可以根据下面的步骤来再现这一个问题。

    创建自定义行为(服务行为、终结点行为、契约行为和操作行为)是对WCF进行扩展最为常用的形式。通过下面的代码,我们创建了一个自定义的服务行为,为了简单我们没有编写任何逻辑代码。

       1: namespace Artech.Bug4BehaviorExtension
       2: {    
       3:     public class FooBehavior : IServiceBehavior
       4:     {
       5:         public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { }
       6:  
       7:         public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
       8:  
       9:         public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
      10:     }    
      11: }

    自定义服务行为可以通过两种方式应用到WCF运行时框架中:自定义特性(Attribute)和配置。现在我们采用后面一种,为此我们需要为上面创建的FooBehavior创建相应的BehaviorExtensionElement(本质上是一个ConfigurationElement):FooBehaviorElement。

       1: namespace Artech.Bug4BehaviorExtension
       2: {
       3:     public class FooBehaviorElement : BehaviorExtensionElement
       4:     {
       5:         public override Type BehaviorType
       6:         {
       7:             get { return typeof(FooBehavior); }
       8:         }
       9:  
      10:         protected override object CreateBehavior()
      11:         {
      12:             return new FooBehavior();
      13:         }
      14:     }
      15: }

    接下来,我们创建一个简单的WCF服务来使用上面的服务行为,下面是服务和服务契约的定义。

       1: namespace Artech.Bug4BehaviorExtension
       2: {    
       3:     [ServiceContract(Namespace="http://www.artech.com/")]
       4:     public interface ICalculator
       5:     {
       6:         [OperationContract]
       7:         double Add(double x, double y);
       8:     }
       9:  
      10:     public class CalculatorService : ICalculator
      11:     {
      12:         public double Add(double x, double y)
      13:         {
      14:             return x + y;
      15:         }
      16:     }    
      17: }

    我采用IIS寄宿(Host)的方式来寄宿CalculatorService服务,为此我们创建一个.svc文件。该文件的内容如下:

       1: <%@ ServiceHost Service="Artech.Bug4BehaviorExtension.CalculatorService"%>

    通过如下的配置,上面定义的FooBehavior被应用到了CalculatorService服务上面。行为扩展的类型为:“Artech.Bug4BehaviorExtension.FooBehaviorElement, Artech.Bug4BehaviorExtension”(注意这是关键)。

       1: <?xml version="1.0" encoding="utf-8" ?>
       2: <configuration>
       3:     <system.serviceModel>
       4:         <behaviors>
       5:             <serviceBehaviors>
       6:                 <behavior name="myServiceBehavior">
       7:                     <foo/>
       8:                     <serviceMetadata httpGetEnabled="true"/>
       9:                 </behavior>
      10:             </serviceBehaviors>
      11:         </behaviors>
      12:         <extensions>
      13:             <behaviorExtensions>
      14:                 <add name="foo" type="Artech.Bug4BehaviorExtension.FooBehaviorElement, Artech.Bug4BehaviorExtension" />
      15:             </behaviorExtensions>
      16:         </extensions>
      17:         <services>
      18:             <service behaviorConfiguration="myServiceBehavior" name="Artech.Bug4BehaviorExtension.CalculatorService">
      19:                 <endpoint binding="ws2007HttpBinding" contract="Artech.Bug4BehaviorExtension.ICalculator" />
      20:                 <host>
      21:                     <baseAddresses>
      22:                         <add baseAddress="http://127.0.0.1:3721/calculatorservice" />
      23:                     </baseAddresses>
      24:                 </host>
      25:             </service>
      26:         </services>
      27:     </system.serviceModel>
      28: </configuration>

    现在我们通过IE直接访问服务的地址,你会看到如下的界面——这基本上可以表面我们的服务被成功发布。

    image现在我们做一个非常微小的改变,将扩展行为类型从"Artech.Bug4BehaviorExtension.FooBehaviorElement, Artech.Bug4BehaviorExtension” 改成“Artech.Bug4BehaviorExtension.FooBehaviorElement,Artech.Bug4BehaviorExtension”。可能你都没有注意到到底我做了怎样的改动,提醒你一下:我们将类型名称和程序基名称之间的空格去掉了

       1: <?xml version="1.0" encoding="utf-8" ?>
       2: <configuration>
       3:     <system.serviceModel>
       4:         <behaviors>
       5:             <serviceBehaviors>
       6:                 <behavior name="myServiceBehavior">
       7:                     <foo/>
       8:                     <serviceMetadata httpGetEnabled="true"/>
       9:                 </behavior>
      10:             </serviceBehaviors>
      11:         </behaviors>
      12:         <extensions>
      13:             <behaviorExtensions>
      14:                 <add name="foo" type="Artech.Bug4BehaviorExtension.FooBehaviorElement,Artech.Bug4BehaviorExtension" />
      15:             </behaviorExtensions>
      16:         </extensions>
      17:         <services>
      18:             <service behaviorConfiguration="myServiceBehavior" name="Artech.Bug4BehaviorExtension.CalculatorService">
      19:                 <endpoint binding="ws2007HttpBinding" contract="Artech.Bug4BehaviorExtension.ICalculator" />
      20:                 <host>
      21:                     <baseAddresses>
      22:                         <add baseAddress="http://127.0.0.1:3721/calculatorservice" />
      23:                     </baseAddresses>
      24:                 </host>
      25:             </service>
      26:         </services>
      27:     </system.serviceModel>
      28: </configuration>

    现在再次刷新IE页面,你将会得到如下的结果。页面上的错误信息表明:我们定义的行为扩展类型无法被WCF解析——仅仅删除了一个小小的空格,WCF就不能正确地解析类型,这彻底让我无语。在本章的开篇我已经说过,这个问题我在很多年前就遇到过。因为我习惯于手工进行WCF的配置,在进行WCF扩展相关配置的时候,我经常发现我的服务访问不了,但是怎么也找不到问题的症结。然后通过VS提供的配置工具去配置,发现服务可以正常访问。然后两者进行对比,也没有发现有什么差异。其实在那种情况下,即使我发现多一个空格这种差异,我也不会觉得这种差别就是问题的症结所在。隐约记得有位读者在我的Blog上有过相关的留言,当时也没有在意,所以这个问题就一直没有深究。我想肯定会有人之前就发现过这个问题,肯定还会有后继者会遇到这个问题。为此,写下了这篇没有什么技术含量的博文,希望遇到相似问题但百思不得其解的人能够发现这篇文章。

    image

    作者:Artech
    出处:http://artech.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    [原创]网页级在线性能测试网站介绍
    [原创]浅谈测试团队文化
    [原创]浅谈自动化测试中的金字塔模型理解
    [原创]如何在面试时选择合适的测试人员?
    [原创]浅谈怎么写周报
    [原创]Windows下调试工具介绍
    [原创]浅谈我对持续集成的理解
    [原创]IBM AppScan工具培训
    [原创]Jenkins持续集成工具介绍
    [原创]什么是信息安全资产管理?
  • 原文地址:https://www.cnblogs.com/artech/p/1828395.html
Copyright © 2020-2023  润新知