好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

WCF方法拦截及OperationInvoker传递参数到WCF方法的实现

WCF方法拦截及OperationInvoker传递参数到WCF方法的实现

鉴于一些理由需要拦截WCF方法,比如参数的检测。一个实际的场景是CSRF防范中需要对CsrfToken的检测。
要实现拦截,在形式上要实现两点:
1:为WCF方法增加特性类;
2:捕获WCF方法;
第一点很好实现,实现一个Attribute类。第二点则可以利用WCF框架中的IOperationInvoker接口,让该Attribute类同时也实现该接口,同时在该接口方法的ApplyDispatchBehavior方法中,为dispatchOperation实现一个新的OperationInvoker。 

 public   class   MyOperationInterceptorAttribute : Attribute, IOperationBehavior
{
    
      public   void   AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
    { }

      public   void   ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
    { }

      public   void   ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
    {
        dispatchOperation.Invoker  =  new   
    }

      public   void   Validate(OperationDescription operationDescription)
    { }
}


  public   class   MyInvoker : IOperationInvoker
{
    IOperationInvoker m_OldInvoker;    

      public   object  Invoke( object  instance,  object [] inputs,  out   object  [] outputs)
    {
          try  
        {
          //  do something 
             object  result = m_OldInvoker.Invoke(instance, inputs,  out   outputParams);
              return   result;
        }
          catch   (Exception err)
        {
            outputs  =  new   object [ 0  ];
          //  do catch 
             return   null  ;
        }
          finally  
        {
            
        }
    }

      public   virtual   object  [] AllocateInputs()
    {
          return   m_OldInvoker.AllocateInputs();
    }
    
      public  IAsyncResult InvokeBegin( object  instance,  object [] inputs, AsyncCallback callback,  object   state)
    {
          return   m_OldInvoker.InvokeBegin(instance, inputs, callback, state);
    }

      public   object  InvokeEnd( object  instance,  out   object  [] outputs, IAsyncResult result)
    {
        
          return  m_OldInvoker.InvokeEnd(instance,  out   outputs, result);
        
    }

      public   bool   IsSynchronous
    {
          get  
        {
              return   m_OldInvoker.IsSynchronous;
        }
    }
} 

如果我们将服务宿主在IIS中,则这种实现的好处是我们可以完全不需要更改配置文件就能实现对WCF方法的拦截。
这种方式还有一种好处是,我们可以解析客户端发送过来的内容,并统一进行处理,而无需为WCF方法增加参数。如,我们对CSRF方法的时候,客户端发送过来的内容中会含有CSRFToken,传统的做法是为WCF方法一个CSRFToken的参数,如下:

 public   void  DoSomething( string  arg0,  string   csrfToken)
{
    Check(csrfToken);
    ...
} 

并且每个需要处理CSRF的方法中都要进行如上编码,而现在只要变成:

 [MyOperationInterceptor]
  public   void  DoSomething( string   arg0)
{
    ...
} 

可以看到少了参数,少了方法内的处理,当然,我们需要在MyInvoker类的Invoke方法的//do something处解析前台内容,获取CSRFToken,并进行Check,获取CSRFToken如下实现:

 string   GetToken()
{
      //  rest or soap 
     string  token = HttpContext.Current.Request.QueryString[ "  token  "  ];
      if ( string  .IsNullOrEmpty(token))
    {
        XDocument doc  =  XDocument.Parse(OperationContext.Current.RequestContext.RequestMessage.ToString());
          var  rootElements = ( from  p  in  doc.Descendants( "  root  " )  select   p).Elements();
          var  args = ( from  p  in  rootElements  select   new  {Name=p.Name.LocalName, Value=p.Value}).ToList( 0  ;
        token  = ( from  p  in  args  where  p.Name= "  token  "   select   p.Value).First();
    }
      return   token;
} 

在这种拦截的应用中,有时候我们难免要将拦截过程中的一些内容传递到WCF方法中,如果有这样的需求,则可以将这些内容放置到OperationContet.Current.IncomingMessageProperties中,它是一个IDictionary<string, object>,当然,要对这个参数进行存取的时候,我们需要用到OperationContextScope,于是,整个MyInvoker类的Invoke方法变成如下的形式:

         try  
        {
          using (OperationContextScope scope =  new   OperationContextScope())
        {
              //  get token and check 
        OperationContet.Current.IncomingMessageProperties.Add( "  SomeKey  "  , SomeObjectInstance);
              //  do something 
             object  result = m_OldInvoker.Invoke(instance, inputs,  out   outputParams);
              return   result;
        }
        }
          catch   (Exception err)
        {
            outputs  =  new   object [ 0  ];
          //  do catch 
             return   null  ;
        }
          finally  
        {
            
        } 

在具体的WCF方法中,如果要使用这个SomeObjectInstance,则可以这样获得:
 SomeObjectInstance = OperationContet.Current.IncomingMessageProperties["SomeKeyas TheInstanceType;


本文出处: http://www.cnblogs.com/luminji/  
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于WCF方法拦截及OperationInvoker传递参数到WCF方法的实现的详细内容...

  阅读:40次