WCF系列(1)—— CustomBehavior 入门

  由于最近工作一直在做wcf平台上的开发,所以决定先结合自己平时工作中的经验实践写一个WCF的系列,希望能对大家有所帮助。

   首先,说到WCF,就不得不提Endpoint这个概念,而Endpoint则由ABC组成,Adress,BindingContract。对于这些基础的知识,我向大家推荐Artech写的一个系列,大家可以去读一下,我觉得写得非常好,读罢获益匪浅。

    http://www.cnblogs.com/artech/archive/2007/02/28/659331.html

接着来说ABC的问题。在Binding里面我们只能指定编码方式而不能指定序列化的方式,序列化的方式只能在程序里面指定。而最近我们的team遇到了这样一个需求,大致要求如下:

1.       我们team当前研发的web servicerestful的,而我们希望用户能在request里面输入一个”alt=xml”或者”alt=json”来决定返回的数据格式是xml或者json

2.       我们希望动态决定返回数据这个功能是独立的,可插拔的模块,并且可以方便地决定哪些service用这个功能而哪些service不用这个功能

3.       我们希望可以通过配置的方式来插拔这个功能

 好了,大致需求就这么多。针对以上需求,我们想到写一个Custom Behavior来实现这些需求。

 对于Custom Behavior, 先做一点基本知识的阐述:

   我们可以在五个不同的点来定制我们自己的Custom Behavior

   ParameterInspection

   MessageFormatting

   OperationInvoker

   MessageInspection

   OperationSelector

   由于这个需求是需要根据用户输入的参数来动态的决定返回的response的格式,所以我当时选择写一个MessageFormatterCustomBehavior

   然后CustomBehavior分以下几种:

   ServiceBehavior

   EndpointBehavior

   ContractBehavior

   OperationBehavior

WCF里面,有三种方式来添加behavior:

 

ServiceBehavior

EndpointBehavior

ContractBehavior

OperationBehavior

通过代码方式添加

 

 

 

 

 

 

 

 

通过Attribute的方式

 

 

 

 

 

 

通过配置的方式

 

 

 

 

 

 

 

 

 

 好了根据以上阐述,由于我们想使用配置来插拔该功能,所以我们选用Endpoint Behavior

     然后,我们可以自己实现一个IDispatchMessageFormatter

 

   

  public  class MessageFormatter : IDispatchMessageFormatter
    {
         private  const  string CONTENT_TYPE_XML =  " text/xml ";
         private  const  string CONTENT_TYPE_JSON =  " application/Json ";
         private  readonly IDispatchMessageFormatter originalFormatter;

         public MessageFormatter(IDispatchMessageFormatter dispatchMessageFormatter)
        {
             this.originalFormatter = dispatchMessageFormatter;
        }

         #region IDispatchMessageFormatter
         public  void DeserializeRequest(Message message,  object[] parameters)
        {
             this.originalFormatter.DeserializeRequest(message,parameters);
        }

         public Message SerializeReply(MessageVersion messageVersion,  object[] parameters,  object result)
        {
        }

        #endregion
    }

   我们需要实现反序列化和序列化的2个方法。

  而根据现有的需求,我们可以用WCF中默认的DataContract序列化,因为DataContract序列化既可以序列化出xml也可以序列化出Json,所以我们只需要给Model打上DataContract标签和DataMember标签即可。

  我们可以在SerializeReply方法中做如下操作

  

string alt = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters[ " alt "];
if(alt== " xml ")
{
   WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Xml;
   WebOperationContext.Current.OutgoingResponse.ContentType = CONTENT_TYPE_XML;
}

if(alt== " json ")
{
   WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Json;
   WebOperationContext.Current.OutgoingResponse.ContentType = CONTENT_TYPE_JSON;
}

 

  然后,我们需要把这个MessageFormatter加到一个EndpointBehavior里面去。

  我们可以实现一个Endpoint Behavior

 

  public  class MessageFormatterEndpointBehavior : IEndpointBehavior
    {
         #region IEndpointBehavior Members
         public  void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

         public  void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
        }

         public  void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
             foreach (OperationDescription operation  in endpoint.Contract.Operations)
            {
                operation.Formatter =  new MessageFormatter(operation.Formatter);
            }
        }

         public  void Validate(ServiceEndpoint endpoint)
        {
        }
         #endregion
    }

 

  接下来,由于Endpoint Behavior是不能直接写进配置文件中的,为了实现可配置,我们需要为我们的Endpoint Behavior写一个Extension Element.

  

     public  class MessageFormatterEndpointBehaviorExtensionElement : BehaviorExtensionElement
    {
         public  override Type BehaviorType
        {
             get {  return  typeof(MessageFormatterEndpointBehavior); }
        }

         protected  override  object CreateBehavior()
        {
             return  new MessageFormatterEndpointBehavior();
        }
    }

  然后,再把这个extension element配置到文件中。

 

<system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding name= " webBinding ">
        </binding>
      </webHttpBinding>
    </bindings>
    <services>
      <service name= " WCFMessageFormatter.Services.TankService " behaviorConfiguration= " testServiceBehavior ">
        <endpoint address= " http://localhost:8080/TankService " behaviorConfiguration= " webBehavior "
                  binding= " webHttpBinding " bindingConfiguration= " webBinding " contract= " WCFMessageFormatter.Contracts.ServiceContracts.ITankService ">
        </endpoint>
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name= " webBehavior ">
          <webHttp />
           <endpointMessageFormatter />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name= " testServiceBehavior ">
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <extensions>
       <behaviorExtensions>
        <add
          name= " endpointMessageFormatter "
          type= " WCFMessageFormatter.CustomServiceBehaviors.MessageFormatterEndpointBehaviorExtensionElement, WCFMessageFormatter.CustomServiceBehaviors, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null "
          />
      </behaviorExtensions>
    </extensions>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests= " true ">
      <add name= " UrlRoutingModule " type= " System.Web.Routing.UrlRoutingModule,System.Web.Routing,Version=4.0.0.0,Culture=neutral,PublicKeyToken=31BF3856AD364E35 " />
    </modules>
  </system.webServer>
</configuration>

  好了,这样一来就可以实现我们需求中提到的功能了。

  在下一节中,我将继续这个例子来说说WCF Custom Behavior和序列化的相关内容,下一篇中将提到几个需求变化以及我们如何应对这些变化。

  在这个例子写完时我将附上完整的项目代码。

  另外,最近也有一些朋友通过博客园上的联系方式与我联系,时间关系,我并不能对所有问题都做出回答,十分抱歉,大家有任何问题还是可以给我留言,或者邮件,QQ联系,我会尽量回复。

转载于:https://www.cnblogs.com/FlyEdward/archive/2012/06/25/WCF_CustomBehavior.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值