前面的文章中,老周已向大伙伴们介绍了如何在终结点上使用地址头,只要服务是沿着该终结点调用的,那么每一次调用都会自动把地址头插入到SOAP消息的Header列表中。

而通过前一篇文章中的示例,大家也看到,客户端在调用服务时,必须指定与服务器完全一致的地址头,否则会验证失败。那是因为,在默认情况下,AddressFilter会对终结点的地址以及地址头进行校验。如果我们不希望使用默认校验行为,可以自定义一个MessageFiler,然后对传入的SOAP消息头进行验证。

MessageFilter是一个抽象类,它的结构如下:

    public abstract class MessageFilter
{
……
public abstract bool Match(MessageBuffer buffer); public abstract bool Match(Message message);
……
}

我们重点要实现Match方法,如果校验成功,则返回true,如果不通过就返回false。Match方法有两个重载,我们核心要做的是处理参数类型为Message的版本,而参数类型为MessageBuffer的版本,只需要从buffer中读出一条SOAP消息,并传递给bool Match(Message message)方法即可。

下面代码演示该处理。

        public override bool Match(MessageBuffer buffer)
{
Message msg = buffer.CreateMessage();
bool b= Match(msg);
msg.Close();
return b;
}

CreateMessage方法从字节缓冲区生成一条消息实例,然后调用另一个Match方法,并得到验证结果,最后把结果返回即可。由于此处的Message是从buffer产生的临时消息实例,因此用完后,可以调用Close方法释放掉。

接下来,我们重点实现参数类型为Message的Match方法重载。本例子我主要验证客户端的地址头中是否包含一个名为vip的XML元素,命名空间为member-vip,并且,XML元素内有一个名为star的attribute。假设它表示VIP会员的星级,比如一个购书服务程序,不同星级的VIP可以获得不折扣的优惠。

即客户端在调用时应提供这样的地址头:

<vip xmlns="member-vip" star="2" />

咱们这个自定义MessageFilter的任务是检查消息头中是否存在vip元素,且命名空间为member-vip,包含star特性。

        public override bool Match(Message message)
{
var hd = message.Headers.FirstOrDefault(h => h.Namespace == HEADER_NS && h.Name == HEADER_ELNAME);
if (hd == null) return false; XElement ele = message.Headers.GetHeader<XElement>(HEADER_ELNAME, HEADER_NS); if (ele.Attributes("star").Count() == )
{
return false;
}
return true;
}

筛选器是在消息调度阶段执行的,负责对终结点进行调度的是EndpointDispatcher类,它有一个AddressFilter属性,引用的类型正是MessageFilter的派生类。故,我们只要把自定义的消息筛选器实例赋给AddressFilter属性即可,那么,如何赋值呢?

WCF为每个服务部分都提供了Behavior,不同的Behavior用于扩展不同的对象。比如,对服务本身,可以用Service Behavior来扩展;对于终结点,可以用Endpoint Behavior来扩展;对于服务协定,可以用Contract Behavior来扩展,等等。Behavior可以对各个对象的功能进行扩充,但在扩展时应当注意,扩展点最好与behavior相对应,即,如果扩展点是扩展终结点的行为的,就应该用Endpoint Behavior来扩展,而不要用Cannel Behavior来扩展。

AddressFilter是作用在终结点上的,所以,在扩展时应该实现IEndpointBehavior接口。不管是哪一种类型的behavior,通常我们在实现时,会实现以下两个方法:

ApplyDispatchBehavior——指的是behavior在服务器上被应用后的处理。

ApplyClientBehavior——指在客户端应用behavior后的处理。

AddressFilter只需要在服务器端进行处理,而不必考虑客户端,所以,重点实现ApplyDispatchBehavior方法即可。

    public class MyEndpointBehavior : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{ } public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{ } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.AddressFilter = new MyEndpointAddrFilter();
} public void Validate(ServiceEndpoint endpoint)
{ }
}

很简单,直接把自定义的MessageFilter实例赋值给AddressFilter属性就可以了。Validate方法是用来验证当前的终结点是否合法,本例中不用进行检验,如果你验证的话可以写上相应的代码,如果终结点不合法,直接抛出异常就行了。

随后,把这个自定义的终结点behavior插入到服务的终结点中即可。

            using (ServiceHost host=new ServiceHost(typeof(SV)))
{
foreach (var svep in host.Description.Endpoints)
{
if (svep.EndpointBehaviors.Contains(typeof(MyEndpointBehavior)) == false)
{
svep.EndpointBehaviors.Add(new MyEndpointBehavior());
}
} host.Open(); ………………

现在自定义的地址头筛选器已经起作用了。

目前这个Behavior不支持配置文件,只能使用代码来插入到ServiceEndpoint中。

要是希望该behavior可以通过配置文件使用,可以实现BehaviorExtensionElement抽象类。代码如下:

    public sealed class CustEndpointBehaviorElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get
{
return typeof(MyEndpointBehavior);
}
} protected override object CreateBehavior()
{
return new MyEndpointBehavior();
}
}

BehaviorType属性返回自定义behavior类型的Type,此处是MyEndpointBehavior类的Type。CreateBehavior方法返回自定义behavior的实例,此处当然是MyEndpointBehavior的实例了。

打开配置文件,在system.serviceModel节点下添加以下扩展声明:

  <system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="CustomEndpointBehavior" type="TestApp.CustEndpointBehaviorElement,TestApp"/>
</behaviorExtensions>
</extensions>
</system.serviceModel>

name指定的是随后在配置文件中使用该扩展时的元素名称,type指定类型,类名要包含命名空间,逗号后面是程序集名称。

现在可以在behaviors节点下声明了。

  <behaviors>
<endpointBehaviors>
<behavior name="svepbhv">
<CustomEndpointBehavior />
</behavior>
</endpointBehaviors>
</behaviors>

behavior的节点名称就是刚才在behaviorExtensions / add 下指定的name值。

最后,记得在endpoint节点上引用behavior配置。

   <endpoint address="http://localhost:2288/demo" …… behaviorConfiguration="svepbhv"/>

好了,如此一来,自定义的地址头筛选方案就完成了。

看起来像是复杂一些,其实也没什么,总结起来就是:扩MessageFilter --> 扩Behavior --> 应用behavior,另外附加的就是实现BehaviorExtensionElement类,这只是为了让其支持配置文件。

本文示例代码下载地址

【WCF】自定义地址头的筛选器的更多相关文章

  1. WCF自定义地址路由映射(不用svc文件)

    一般在创建WCF服务时会用Serivce.svc文件访问,地址如:http://localhost/applicationname/Serivce.svc/Name 现在用路由映射成:http://l ...

  2. 【WCF】为终结点地址应用地址头

    记得不久前,老周写过博文,探讨过在ContextScope以一定的范内向发出的消息中插入消息头,scope只能为特定的某一次服务操作的调用而添加SOAP头,要是需要在每次调用操作协定的时候都插上Hea ...

  3. WebApi:自定义筛选器

    最近在项目中有这样一个需求,记录每次Api访问的调用时间,运行时间,传入数据,返回数据等信息. 第一反应就是添加一个类,用来实现相应的功能,然后在方法的代码中添加,但是这样的话,需要修改所有的方法的代 ...

  4. Asp.Net MVC 页面代码压缩筛选器-自定义删除无效内容

    Asp.Net MVC 页面代码压缩筛选器 首先定义以下筛选器,用于代码压缩. /*页面压缩 筛选器*/ public class WhiteSpaceFilter : Stream { privat ...

  5. ASP.NET MVC 如何使用自定义过滤器(筛选器)

    继承*****Attribute(筛选器三种具体类)-->重写方法-->标记在控制器 或者 方法上面 或者 在FilterConfig中Add [类名(类属性 = 值)]还有[AllowA ...

  6. [转载]开发 Spring 自定义视图和视图解析器

    原文出处 http://www.ibm.com/developerworks/cn/java/j-lo-springview/ 概述 Spring 3.0 默认包含了多种视图和视图解析器,比如 JSP ...

  7. Magicodes.IE之导入导出筛选器

    总体设计   Magicodes.IE是一个导入导出通用库,支持Dto导入导出以及动态导出,支持Excel.Word.Pdf.Csv和Html.在本篇教程,笔者将讲述如何使用Magicodes.IE的 ...

  8. jQuery---jq基础了解(语法,特性),JQ和JS的区别对比,JQ和JS相互转换,Jquery的选择器(基础选择器,层级选择器,属性选择器),Jquery的筛选器(基本筛选器,表单筛选器),Jquery筛选方法

    jQuery---jq基础了解(语法,特性),JQ和JS的区别对比,JQ和JS相互转换,Jquery的选择器(基础选择器,层级选择器,属性选择器),Jquery的筛选器(基本筛选器,表单筛选器),Jq ...

  9. VS工具如何新建筛选器

    最近,遇到了一个问题,别人用VS工具新建了一个工程,不知道怎么的,就是没有办法新建筛选器. 今天,终于解决了,记录下,也希望能够帮助更多的人. 当我们的工程目录里的文件越来越多的时候,这时候需要建立帅 ...

随机推荐

  1. 【疯狂造轮子-iOS】JSON转Model系列之二

    [疯狂造轮子-iOS]JSON转Model系列之二 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇<[疯狂造轮子-iOS]JSON转Model系列之一> ...

  2. GreenDao 数据库:使用Raw文件夹下的数据库文件以及数据库升级

    一.使用Raw文件夹下的数据库文件 在使用GreenDao框架时,数据库和数据表都是根据生成的框架代码来自动创建的,从生成的DaoMaster中的OpenHelper类可以看出: public sta ...

  3. 梅须逊雪三分白,雪却输梅一段香——CSS动画与JavaScript动画

    CSS动画并不是绝对比JavaScript动画性能更优越,开源动画库Velocity.js等就展现了强劲的性能. 一.两者的主要区别 先开门见山的说说两者之间的区别. 1)CSS动画: 基于CSS的动 ...

  4. 通过ProGet搭建一个内部的Nuget服务器

    .NET Core项目完全使用Nuget 管理组件之间的依赖关系,Nuget已经成为.NET 生态系统中不可或缺的一个组件,从项目角度,将项目中各种组件的引用统统交给NuGet,添加组件/删除组件/以 ...

  5. Centos 下 mysql root 密码重置

    重置mysql密码的方法有很多,官网也提供了很方便的快捷操作办法,可参考资料 resetting permissions .本文重置密码的具体步骤如下: 一.停止MySQL(如果处于运行状态) #se ...

  6. C#制作简易屏保

    前言:前段时间,有个网友问我C#制作屏保的问题,我瞬间懵逼了(C#还可以制作屏保!).于是我去查阅相关资料,下面把C#如何制作屏保的过程及我学习过程的心得也记录下来,希望对需要的人能有帮助. 基本思路 ...

  7. 设计模式C#合集--单例模式

    单例模式 代码: 第一种: private static Singleton singleton = null; private Singleton() { } public static Singl ...

  8. 推荐10款超级有趣的HTML5小游戏

    HTML5的发展速度比任何人的都想像都要更快.更加强大有效的和专业的解决方案已经被开发......甚至在游戏世界中!这里跟大家分享有10款超级趣味的HTML5游戏,希望大家能够喜欢! Kern Typ ...

  9. jquery-treegrid树状表格的使用(.Net平台)

    上一篇介绍了DataTable,这一篇在DT的基础之上再使用jquery的一款插件:treegrid,官网地址:http://maxazan.github.io/jquery-treegrid/ 一. ...

  10. BPM公文管理解决方案分享

    一.方案概述 公文作为一种规范性文书,具有法律性.指导性.政令性强的特点,是企事业单位政令上通下达的重要方式.及时.准确.安全地处理.控制和管理公文,方能保障企事业单位正常运转,确保组织权威和政令畅通 ...