• 利用定制行为扩展WCF之利用MessageInsepctor behaviourExtension扩展WCF行为(自定义消息头)


    有关如何进行WCF 扩展的基础知识,如下:
    ==========
    当我们需要扩展
    WCF的功能,或者需要实现某些特定的功能,我们必须应用WCF的扩展定制功能(WCF extension)

    1.       WCF定制行为相关的namespace
    用来扩展WCF扩展行为的namespace主要包括2个:
    a. System.ServiceModel.Disptcher:
    namespace主要用来用来定制行为,他们可以用来扩展WCF的服务模型。
    b. System.ServiceModel.Channels:
    namespace用来定义定制绑定元素,它们可以扩展WCF的信道层。

    2.       定制行为的分类

    3.       实现定制行为的步骤
    实现定制行为一般分为3步:
    1. 声明扩展:
         声明所要提供的行为的类型, 例如是工作在客户端中以将发送的数据序列化到消息里,还是工作在服务中以管理服务类型的实例等等
    2.附加扩展:
        2步需要将所定制的extension附加到相应的操作,终结点或者服务端行为上。
    例如对于客户端来说:

    a.       当他是操作相关(Operation)的时候,则将该定制行为附加到操作上,即实现System.ServiceModel.Description.IOperationBehavior接口。

    b.      当他是终结点(Endppoint)相关的时候 ,则将该定制行为附加到终结点上,即实现System.ServiceModel.Description.IEndpointBehavior接口。

    3.告知(inform)
        告知的作用就是将那些自己定义的扩展行为告知客户端运行时组件(ClientRunTime)或者服务端调度器(EndpointDispatcher)。

    对于附加到操作上的扩展行为,只能采用programatically的方式告知,而对于附加到终结点上的扩张行为,告知的方式有2种,分别为programatically和administratively:
    更多信息,请参阅http://www.cnblogs.com/Winston/archive/2009/02/10/1387260.html

    下面通过一个示例,详细讲解如何通过利用MessageInpector behaviour extension,从而实现在WCF 客户端发出请求之前,添加一个自定义Message Header;在WCF server端接受到该WCF request中,读取该Message Header并作出相应动作。

    首先对MessageInspector扩展作简要介绍。
    MessageInspector(消息检查器)既可以应用在客户端,又可以应用在服务器端。当然,应用于不同端时,其要实现的接口和附加的对象有所不同。
    首先介绍如何实现客户端的MessageInsepector扩展:
    ==========
    第一步:
    实现接口:System.ServiceModel.Dispatcher.IClientMessageInspector;
          其共有2个方法要实现,即BeforeSendRequest和AfterReceiveReply,前者在请求发送之前被自动调用,后者在客户端接受到消息自动调用。如果客户端没有实现这2个接口,那么客户端发送和接受消息的行为就不会被重写,一切照旧 :)
    其接口原形如下:
    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    public void AfterReceiveReply(Message reply,object correlationState)
    如下所示:假设我们在即将发出的消息中加入一个Message Header:"estHeader",则如下所示:

    public class ClientMessageInspectorDemo : System.ServiceModel.Dispatcher.IClientMessageInspector,System.ServiceModel.Description.IEndpointBehavior
       {
           
    #region Implemmentation for IClientMesageInpector
           
    //===================================
    //该方法会在服务器端reply返回后自动调用
           public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply,

                 
    object correlationState)
           {

           }


    //该方法在客户端消息发送之前会被自动调用
           public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request,

               System.ServiceModel.IClientChannel channel)
           {
               Console.WriteLine(
    "BeforeSendRequest is called");
               request.Headers.Add(System.ServiceModel.Channels.MessageHeader.CreateHeader(
    "testHeader","SecurityLog","该Message Header为测试之用"));
               
    return null;

           }
    }

    第二步:
    将第一步的扩张行为附加在ClientRuntime上,即实现System.ServiceModel.Description.IEndpointBehavior的ApplyClientBehavior()方法。如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ServiceModel;
    using System.ServiceModel.Configuration;
    using System.ServiceModel.Dispatcher;
    using System.Configuration;

    namespace SecurityLog
    {
       
    public class ClientMessageInspectorDemo : System.ServiceModel.Dispatcher.IClientMessageInspector,System.ServiceModel.Description.IEndpointBehavior
       {
           
    public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply,

                 
    object correlationState)
           {

           }



           
    public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request,

               System.ServiceModel.IClientChannel channel)
           {
               Console.WriteLine(
    "BeforeSendRequest is called");
               request.Headers.Add(System.ServiceModel.Channels.MessageHeader.CreateHeader(
    "testHeader","SecurityLog","This Message Header is used for testing"));
               
    return null;

           }

           
    #endregion

        
           
    #region Implementation for IEndpointBehavior
           
    //==================================
            public void AddBindingParameters(System.ServiceModel.Description.ServiceEndpoint  serviceEndpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
            {
                
    return;
            }

            
    public void ApplyClientBehavior(System.ServiceModel.Description.ServiceEndpoint  serviceEndpoint, ClientRuntime behavior)
            {
                
    //此处为Extension附加到ClientRuntime。
                behavior.MessageInspectors.Add(this);
               
    // return;
            }

            
    public void ApplyDispatchBehavior(System.ServiceModel.Description.ServiceEndpoint  serviceEndpoint , EndpointDispatcher endpointDispatcher)
            {
                
    //如果是扩展服务器端的MessageInspector,则要附加到EndpointDispacther上了。
                
    //endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
            }

            
    public void Validate(System.ServiceModel.Description.ServiceEndpoint  serviceEndpoint )
            {
                
    return;
            }

            
    #endregion 
        }



        
    public class MyMesssageInspectorExtensionelement : System.ServiceModel.Configuration.BehaviorExtensionElement
        {
            
    public override Type BehaviorType
            {

                
    get { return typeof(ClientMessageInspectorDemo); }

            }

            
    protected override object CreateBehavior()
            {

                
    return new ClientMessageInspectorDemo();

            }

        }


    }


    第三步:
    将定制行为告知WCF (可以通过配置或者编程方式, 我更喜欢用配置方式)
    要通过配置方式告知WCF我们自定义扩展行为的存在,必须提供一个从抽象基类System.ServiceModel.Configuration.BehaviorExtensionElement的类。如下所示:

     public class MyMesssageInspectorExtensionelement : System.ServiceModel.Configuration.BehaviorExtensionElement
        {
            
    public override Type BehaviorType
            {

                
    get { return typeof(ClientMessageInspectorDemo); }

            }

            
    protected override object CreateBehavior()
            {

                
    return new ClientMessageInspectorDemo();

            }
    }

    然后通过适当配置即可,如下所示:


    当客户端发出请求之后,我们可以看到BeforeSendRequest被首先调用,并被写入自定义的Message Header,如下所示:

    下面介绍如何实现服务器端的MessageInspector行为扩展。
    ==========
    第一步:
    实现接口:System.ServiceModel.Dispatcher.IDispatchMessageInspector(不再是客户端的IClientMessageInspector);
          其共有2个方法要实现,即BeforeSendRequest和AfterReceiveReply,前者在请求发送之前被自动调用,后者在客户端接受到消息自动调用。如果客户端没有实现这2个接口,那么客户端发送和接受消息的行为就不会被重写,一切照旧 :)
    其接口原形如下:
    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    public void BeforeSendReply(ref Message reply,object correlationState)

    第二步:附加
    此时要实现的接口是 public void ApplyDispatchBehavior(System.ServiceModel.Description.ServiceEndpoint  serviceEndpoint , EndpointDispatcher endpointDispatcher),不再是附加到客户端时的 public void ApplyClientBehavior(System.ServiceModel.Description.ServiceEndpoint  serviceEndpoint, ClientRuntime behavior)

    第三步:与客户端类似。
    经过以上配置后,在WCF service端就可以接受到写入自定义的Message Header的SOAP包。然后比如我们通过request.Headers.GetHeader<string>("testHeader","SecurityLog")将该testHeader的值获取,根据业务逻辑进行相应操作。
    以下为到达服务器端的SOAP包和testHeader中的内容:

  • 相关阅读:
    python--threading多线程总结
    云服务器 ECS Linux CentOS 修改内核引导顺序
    日记——心刊
    64位linux安装wine等软件
    service: no such service mysqld 与MySQL的开启,关闭和重启
    python调用chrome ie等浏览器
    Linux系统下强制踢掉登录用户
    python读取数据库数据,读取出的中文乱码问题
    jmeter生成时间的函数
    PHP 递归超过100次会自动停止
  • 原文地址:https://www.cnblogs.com/Winston/p/1574902.html
Copyright © 2020-2023  润新知