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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/434450.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Asterisk 可加载模块

app_adsiprog.so > (Asterisk ADSI Programming Application) ——用于支持模拟显示服务接口的终端设备&#xff0c;在终端屏幕上操作菜单等。 app_amd.so > (Answering Machine Detection Application) ——用于外呼时终端应答状态检测 app_authenticate.so > (Aut…

android电梯程序设计,课内资源 - 基于Android实现的电梯调度模拟

一、使用说明1.1 项目简介某一楼有20层&#xff0c;操作者可以通过使用5部电梯从起始楼层来到达指定的楼层。本项目通过实现电梯调度&#xff0c;来模拟实现操作系统的调度过程&#xff0c;并且学习Android环境下使用Java的多线程编程方法以及调度算法。1.2 项目要求操作者可以…

默认构造函数的作用(“A”方法没有采用“0”个参数的重载

构造函数主要用来初始化对象。它又分为静态(static)和实例(instance)构造函数两种类别。大家应该都了解如何来写类的构造函数&#xff0c;这里只说下默认构造函数的作用&#xff0c;以及在类中保留默认构造函数的重要性。实际上&#xff0c;我说错了。正确的说法是&#xff1a;…

SourceInsight 设置点滴

SourceInsight是个强大的代码阅读工具&#xff0c; 价格不菲&#xff0c; 目前除了SlickEdit几乎没有可以与之抗衡的&#xff0c; 可能感觉没什么竞争对手的缘故&#xff0c;SI很少更新。SI的设置选项比较多&#xff0c; 这里说几个比较隐蔽的设置&#xff1a; 1. 改变SI的一些…

asp.net 根据当前时间计算是否股票、期货、黄金交易日期

很简单的一个方法&#xff1a; 股票&#xff1a;每周1到周五&#xff0c;上午9:30到11:30 下午13:00 到15&#xff1a;00 期货&#xff1a;每周1到周五&#xff0c;上午9:00到11:30 下午13:30到15:00 黄金&#xff1a;每周1到周五&#xff0c;上午9:00到11:30 下午13:30到15:…

android mac 照片恢复,如何找回Android手机删除的照片?这方法你肯定不知道

安卓手机怎么恢复误删的照片?如何找回Android手机照片?现在大多数人都喜欢用手机拍照存照片&#xff0c;慢慢的&#xff0c;手机中的照片自然而然就会变多&#xff0c;而照片是最占内存的。当你照片达到一定数量&#xff0c;内存快满的时候&#xff0c;连照片都拍不了。所以就…

Asterisk配置文件说明

Asterisk配置文件说明列表 名称 描述 asterisk.conf 主配置文件&#xff0c;通知Asterisk环境目录位置&#xff0c;包含其他所有配置文件所包含的目录&#xff0c;缺省Asterisk会在/etc/asterisk/目录下找到&#xff0c;也可以通过命令参数使用不同的asterisk.conf zaptel.…

apple watch3连android,Apple watch 可以连android手机吗?

在iOS 8.2正式版更新以后&#xff0c;在手机界面上就多出了一个“Apple Watch”的新图标&#xff0c;这是专门针对苹果新产品Apple Watch的应用&#xff0c;主要作用就是连接iPhone和Apple Watch&#xff0c;并未Apple Watch下载应用。打开“Apple Watch”首先进入的是“我的手…

关闭弹出窗体,刷新父页面

parent.location.reload(); window.opener.location.hrefwindow.opener.location.href; 转载于:https://www.cnblogs.com/xbding/archive/2012/07/03/2574660.html

nubia android root权限,获取中兴NX403a (Nubia Z5S Mini Android 4.2)ROOT权限教程,新手必看...

中兴NX403a (Nubia Z5S Mini Android 4.2)如何获取ROOT权限?用什么ROOT工具最简单?请跟着小编一起来看看如何用奇兔刷机对中兴NX403a (Nubia Z5S Mini Android 4.2)进行一键ROOT&#xff0c;小编特别亲手制作了详细的中兴NX403a (Nubia Z5S Mini Android 4.2) ROOT教程图解&a…

A20 编译

android 源码编译分为 2 个部分&#xff0c;一部分是 linux 内核编译&#xff0c;这部分包括 uboot&#xff0c;另一部分是 android 源码编译。所以编译时各自单独编译&#xff0c;编译成功能&#xff0c;最近单独打包成最终烧录的镜像文件。2.1 源码结构说明首先把源码包 A20-…

apache OFBiz的安装

去官网下载OFBiz的代码包。解压这个代码包进入到命令行&#xff0c;输入以下命令 ant build-all 这时候会自动进行安装。这个过程大概有10多分钟。 运行startofbiz脚本。由于我是windows&#xff0c;所以运行startofbiz.bat。在网址输入http://localhost:8080/ecommerce/可以…

android 沉浸栏灰色,Android 沉浸栏实践——踩坑

当前开发环境&#xff1a;Android Studio 2.1.3&#xff0c;compileSdkVersion 24&#xff0c;buildToolsVersion "24.0.2"&#xff0c;support:appcompat-v7:24.2.0首先放个图&#xff0c;这就是我要做成的效果&#xff0c;Toolbar 和 Status Bar 一体共用背景图&am…

PHP 免费视频教程

http://php.itcast.cn/php/video.shtml?rm转载于:https://www.cnblogs.com/suneryong/archive/2012/07/12/2588325.html

tcp长连接和保活时间

tcp长连接和保活时间TCP协议中有长连接和短连接之分。短连接在数据包发送完成后就会自己断开&#xff0c;长连接在发包完毕后&#xff0c;会在一定的时间内保持连接&#xff0c;即我们通常所说的Keepalive&#xff08;存活定时器&#xff09;功能。 www.2cto.com 默认的Keepa…

android实现文本输入,Android实现智能提示的文本输入框AutoCompleteTextView

今天我们要讲一个十分简单的内容&#xff0c;就是一个安卓控件的使用&#xff0c;用法很简单&#xff0c;但是很常用的一个。这里我用两种不同的写法来处理。当然&#xff0c;无论用哪一种写法&#xff0c;效果都是一样的。我们先来看效果图。要实现这种效果十分简单。需要一个…

【转】系统缓存全解析二:动态缓存(2)-页面局部缓存的两种方式

有时缓存整个页面是不现实的&#xff0c;因为页的某些部分可能在每次请求时都需要变化。在这些情况下&#xff0c;只能缓存页的一部分。顾名思义&#xff0c;页面部分缓存是将页面部分内容保存在内存中以便响应用户请求&#xff0c;而页面其他部分内容则为动态内容。页面部分缓…

TCP心跳机制

所谓的心跳包就是客户端定时放送简单的信息给服务器端&#xff0c;告诉它我还在而已。代码就是每隔几分钟发送一个固定信息给服务器端&#xff0c;服务器端回复一个固定信息。如果服务器端几分钟后没有收到客户端信息则视客户端断开。比如有些通信软件长时间不适用&#xff0c;…

A20成功驱动FT5206触摸屏

经过三个晚上的奋斗&#xff0c;终于在A20上驱动了FT5206触摸屏。实现过程有限蹊跷&#xff0c;现在暂时将实现过程记录下来以免遗忘。 FT5206的驱动在bsp里已经以ko文件的形式提供了&#xff0c;只要在sun7i.init.rc这个系统初始化脚本里加上insmod ft5x_ts.ko即可在系统启动时…

ibatis的简介与初步搭建应用

一、ibatis的简介 ibatis是什么东西就不介绍了&#xff0c;自己去找谷老师。 这里讲下自己的使用体会。之前自己学过Hibernate&#xff0c;是看尚学堂的视频教学的&#xff0c;看完以后发现Hibernate体系中的内容真的很多&#xff0c;什么N-N关联、HSQL、缓存管理等等&#xff…