WCF拦截
Posted 布雷客·希
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WCF拦截相关的知识,希望对你有一定的参考价值。
WCF经常会有一些性能检测,全局异常,跨域设置,动态路由设置等,可以通过以下类实现
(1)拦截类,可以实现性能检测和全局异常处理
/// <summary> /// 使用消息提取的对象以及参数数组,并利用对该对象调用方法,然后返回该方法的返回值和输出参数 /// </summary> public class OperationInvoker : IOperationInvoker { private string _operationMethod;//方法名称 private IOperationInvoker _invoker;//原invoker public OperationInvoker(IOperationInvoker oldInvoker, string operationMethod) { this._invoker = oldInvoker; this._operationMethod = operationMethod; } public object[] AllocateInputs() { return this._invoker.AllocateInputs(); } //System.ServiceModel.Channels.Message HandlePreflight(System.ServiceModel.Channels.Message input, string operationName) //{ // System.ServiceModel.Channels.Message reply = System.ServiceModel.Channels.Message.CreateMessage(MessageVersion.None, operationName); // HttpResponseMessageProperty httpResponse = new HttpResponseMessageProperty(); // httpResponse.SuppressEntityBody = true; // httpResponse.StatusCode = System.Net.HttpStatusCode.OK; // httpResponse.Headers.Set("Access-Control-Allow-Origin", "*"); // httpResponse.Headers.Set("Access-Control-Allow-Methods", string.Join(",", new List<string>() { "POST", "GET", "OPTIONS" })); // reply.Properties.Add(HttpResponseMessageProperty.Name, httpResponse); // return reply; //} /// <summary> /// 从一个实例和输入对象的集合返回一个对象和输出对象的集合 /// </summary> /// <param name="instance"></param> /// <param name="inputs"></param> /// <param name="outputs"></param> /// <returns></returns> public object Invoke(object instance, object[] inputs, out object[] outputs) { this.PreInvoke(instance, inputs); object returnValue = null; object invokeValue; object[] objArray = new object[0]; try { string operationName = ""; if (OperationContext.Current.IncomingMessageHeaders.Action != null) { operationName = OperationContext.Current.IncomingMessageHeaders.Action.ToString(); } if (OperationContext.Current.IncomingMessageProperties.Keys.Contains("HttpOperationName")) { operationName = OperationContext.Current.IncomingMessageProperties["HttpOperationName"].ToString(); } HttpRequestMessageProperty request = System.ServiceModel.OperationContext.Current.IncomingMessageProperties["httpRequest"] as HttpRequestMessageProperty; if (request != null && request.Method == "OPTIONS") { System.ServiceModel.Channels.Message input = (System.ServiceModel.Channels.Message)inputs[0]; outputs = null; return returnValue; } else { invokeValue = this._invoker.Invoke(instance, inputs, out objArray); returnValue = invokeValue; outputs = objArray; } } catch (System.Exception exception) { returnValue = HandleException(exception, instance); outputs = null; } return returnValue; } /// <summary> /// 处理异常 /// </summary> /// <returns></returns> private ResultInfo HandleException(System.Exception exception, object instance) { var res = new ResultInfo(); res.Success = false; res.Message = exception.Message; res.Excetion = new WcfGlobalException(exception.Message, exception.StackTrace, instance, _operationMethod); PackageServiceLib.Helper.EventManager.WriteOutput(exception.Message + exception.StackTrace, LogType.Error); //if (exception != null) //{ // throw exception; //} return res; } public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state) { this.PreInvoke(instance, inputs); return this._invoker.InvokeBegin(instance, inputs, callback, state); } public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result) { object returnValue = null; object invokeValue; object[] objArray = new object[0]; try { invokeValue = this._invoker.InvokeEnd(instance, out outputs, result); returnValue = invokeValue; outputs = objArray; } catch (System.Exception exception) { returnValue = HandleException(exception, instance); outputs = null; } return returnValue; } public bool IsSynchronous { get { return this._invoker.IsSynchronous; } } private void PreInvoke(object instance, object[] inputs) { } }
(2)异常类
[DataContract] public class WcfGlobalException { /// <summary> /// 调用方法的实例 /// </summary> [DataMember(Name = "instance")] public string Instance { set; get; } /// <summary> /// 调用的方法名称 /// </summary> [DataMember(Name = "operationMethod")] public string OperationMethod { set; get; } /// <summary> /// 异常信息 /// </summary> [DataMember(Name = "message")] public string Message { set; get; } /// <summary> /// 异常trace信息 /// </summary> [DataMember(Name = "stackTrace")] public string StackTrace { set; get; } public WcfGlobalException(string message, string trace, object instance, string operationName) { this.Instance = instance.ToString(); this.OperationMethod = operationName; this.Message = message; this.StackTrace = trace; } }
(3)行为特性标签
//BehaviorExtensionElement public class WcfGlobalExceptionOpreationBehaviorAttribute:Attribute,IServiceBehavior { //public override Type BehaviorType //{ // get { return typeof (WcfGlobalExceptionOpreationBehavior); } //} //protected override object CreateBehavior() //{ // return new WcfGlobalExceptionOpreationBehavior(); //} private readonly Type _errorHandlerType; public WcfGlobalExceptionOpreationBehaviorAttribute(Type handlerType) { _errorHandlerType = handlerType; } public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { } /// <summary> /// 注入自定义异常处理程序 /// </summary> /// <param name="serviceDescription"></param> /// <param name="serviceHostBase"></param> public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) { var handler = (IErrorHandler) Activator.CreateInstance(_errorHandlerType); foreach (ChannelDispatcher dis in serviceHostBase.ChannelDispatchers) { dis.ErrorHandlers.Add(handler); } } public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) { } }
(4)操作的拦截特性
public class WcfGlobalOperationInterceptorAttribute:Attribute,IOperationBehavior { private string _operationMethod; public WcfGlobalOperationInterceptorAttribute(string methodName) { this._operationMethod = methodName; } public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation) { } public void ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation) { IOperationInvoker invoke = dispatchOperation.Invoker; dispatchOperation.Invoker = CreateInvoker(invoke); } public void Validate(OperationDescription operationDescription) { } protected OperationInvoker CreateInvoker(IOperationInvoker oldInvoker) { return new OperationInvoker(oldInvoker, this._operationMethod); } }
(5)服务类的拦截特性
[AttributeUsage(AttributeTargets.Class)] public class WcfGlobalServiceInterceptorAttribute:Attribute,IServiceBehavior { public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) { EnableCrossOriginResourceSharingBehavior crossOriginBehavior = new EnableCrossOriginResourceSharingBehavior(); foreach (var endpoint in serviceDescription.Endpoints) { endpoint.Behaviors.Add(crossOriginBehavior); foreach (var operation in endpoint.Contract.Operations) {
if (!operation.Behaviors.Any(d => d is WebGetAttribute)
&& !operation.Behaviors.Any(d => d is WebInvokeAttribute))
{
WebInvokeAttribute wia = new WebInvokeAttribute();
wia.UriTemplate = operation.Name;
wia.Method = "*";
operation.Behaviors.Add(wia);
}
bool flag = false; foreach (var operationBehavior in operation.Behaviors) { if (operationBehavior is WcfGlobalOperationInterceptorAttribute) { flag = true; break; } } if (!flag) { operation.Behaviors.Add(CreateOperationInterceptor(operation.Name)); } } } } public void Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) { } protected WcfGlobalOperationInterceptorAttribute CreateOperationInterceptor(string operationMethod) { return new WcfGlobalOperationInterceptorAttribute(operationMethod); } } public class CustomHeaderMessageInspector : IDispatchMessageInspector { Dictionary<string, string> requiredHeaders; public CustomHeaderMessageInspector(Dictionary<string, string> headers) { requiredHeaders = headers ?? new Dictionary<string, string>(); } public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext) { return null; } public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState) { var httpHeader = reply.Properties["httpResponse"] as HttpResponseMessageProperty; foreach (var item in requiredHeaders) { httpHeader.Headers.Add(item.Key, item.Value); } } } public class EnableCrossOriginResourceSharingBehavior : BehaviorExtensionElement, IEndpointBehavior { public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime) { } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) { var requiredHeaders = new Dictionary<string, string>(); var allOrigin= ConfigurationManager.AppSettings["allowOrigin"].ToString(); requiredHeaders.Add("Access-Control-Allow-Origin", allOrigin); requiredHeaders.Add("Access-Control-Request-Method", "POST,GET,PUT,DELETE,OPTIONS"); requiredHeaders.Add("Access-Control-Allow-Headers", "X-Requested-With,Content-Type"); requiredHeaders.Add("Access-Control-Allow-Credentials", "true"); endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new CustomHeaderMessageInspector(requiredHeaders)); } public void Validate(ServiceEndpoint endpoint) { } public override Type BehaviorType { get { return typeof(EnableCrossOriginResourceSharingBehavior); } } protected override object CreateBehavior() { return new EnableCrossOriginResourceSharingBehavior(); } }
文件下载:http://files.cnblogs.com/files/caiyongxi/WCFHelper.zip
以上是关于WCF拦截的主要内容,如果未能解决你的问题,请参考以下文章
如何使 WCF 数据服务查询拦截器以 JSON 格式返回结果?
C# 中 WCF 和 MVC Web API 的通用请求响应拦截器
ASP.Net WCF 服务的 Thread.CurrentPrincipal 被联邦 (WIF) 环境中的某些拦截器丢弃