WCF方法拦截及OperationInvoker传递参数到WCF方法的实现
2013-11-27 14:03
501 查看
鉴于一些理由需要拦截WCF方法,比如参数的检测。一个实际的场景是CSRF防范中需要对CsrfToken的检测。
要实现拦截,在形式上要实现两点:
1:为WCF方法增加特性类;
2:捕获WCF方法;
第一点很好实现,实现一个Attribute类。第二点则可以利用WCF框架中的IOperationInvoker接口,让该Attribute类同时也实现该接口,同时在该接口方法的ApplyDispatchBehavior方法中,为dispatchOperation实现一个新的OperationInvoker。
如果我们将服务宿主在IIS中,则这种实现的好处是我们可以完全不需要更改配置文件就能实现对WCF方法的拦截。
这种方式还有一种好处是,我们可以解析客户端发送过来的内容,并统一进行处理,而无需为WCF方法增加参数。如,我们对CSRF方法的时候,客户端发送过来的内容中会含有CSRFToken,传统的做法是为WCF方法一个CSRFToken的参数,如下:
并且每个需要处理CSRF的方法中都要进行如上编码,而现在只要变成:
可以看到少了参数,少了方法内的处理,当然,我们需要在MyInvoker类的Invoke方法的//do something处解析前台内容,获取CSRFToken,并进行Check,获取CSRFToken如下实现:
在这种拦截的应用中,有时候我们难免要将拦截过程中的一些内容传递到WCF方法中,如果有这样的需求,则可以将这些内容放置到OperationContet.Current.IncomingMessageProperties中,它是一个IDictionary<string, object>,当然,要对这个参数进行存取的时候,我们需要用到OperationContextScope,于是,整个MyInvoker类的Invoke方法变成如下的形式:
在具体的WCF方法中,如果要使用这个SomeObjectInstance,则可以这样获得:
SomeObjectInstance = OperationContet.Current.IncomingMessageProperties["SomeKeyas TheInstanceType;
要实现拦截,在形式上要实现两点:
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;
相关文章推荐
- WCF方法拦截及OperationInvoker传递参数到WCF方法的实现
- WCF方法拦截及OperationInvoker传递参数到WCF方法的实现
- C#中水晶报表实现动态传递参数的简单方法
- json对象转为字符串,当做参数传递时加密解密的实现方法
- 用javascript实现html页面之间的参数传递的四种方法
- Angularjs中$http以post请求通过消息体传递参数的实现方法
- js 与 android 的交互(方法互调用) 和android向 js传递值, js向android传参数 事件拦截看上一篇
- 利用GetType反射方法再调用方法进行传递参数实现调用
- JQuery 绑定事件时传递参数的实现方法
- javascript实现浏览器窗口传递参数的方法
- JavaScript实现向setTimeout执行代码传递参数的方法
- Android编程实现启动另外的APP及传递参数的方法
- html向js方法传递参数具体实现
- Swift - 创建代理协议实现页面间参数传递和方法调用
- javascript实现页面之间传递参数的方法
- JSP几种页面间传递参数实现的方法
- IN(传递参数)加字段原始值实现方法
- JS window 对象 open方法弹窗实现父子窗口中的参数传递
- javascript实现html页面之间参数传递的四种方法实例分析
- 一个内核模块例子(实现调用其他模块中的方法,传递参数等)