WCF-REST IServiceBehavior 对Service 监控 用户访问验证/异常处理...
2013-05-24 21:23
627 查看
通过实现IServiceBehavior 接口,可以对Service 访问时做全局性监控,比如:异常处理、客户端语言版本、以及安全验证
在工厂Opening 过程中,给ServiceHost 添加 Behavior
RestServiceBehavior.cs
在工厂Opening 过程中,给ServiceHost 添加 Behavior
private void Host_Opening(object sender, EventArgs e) { ServiceHost host = sender as ServiceHost; if (host == null) { return; } RestServiceBehavior b = host.Description.Behaviors.Find<RestServiceBehavior>(); if (b == null) { host.Description.Behaviors.Add(new RestServiceBehavior()); } }
RestServiceBehavior.cs
namespace H.Utility.WCF { using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel.Description; using System.ServiceModel; using System.Collections.ObjectModel; using System.ServiceModel.Dispatcher; using System.ServiceModel.Channels; /// <summary> /// 1. 对异常信息的包装,将Service端未捕获的异常转化为JSON返还给客户端 --- RestServiceErrorHandler /// 2. 多语言的处理,将客户端Request信息里的语言信息读出,然后设置当前线程的Culture --- RestServiceParameterInspector /// 3. 使用url参数上的数据来修改Get方式时的http头 --- RestServiceMessageInspector /// </summary> public class RestServiceBehavior : IServiceBehavior { private Type m_BizExceptionType = null; private Type m_ExceptionHandler = null; public RestServiceBehavior() { } public RestServiceBehavior(string customBizExceptionTypeName, string exceptionHandlerTypeName) { if (customBizExceptionTypeName != null && customBizExceptionTypeName.Trim().Length > 0) { m_BizExceptionType = Type.GetType(customBizExceptionTypeName, true); } if (exceptionHandlerTypeName != null && exceptionHandlerTypeName.Trim().Length > 0) { m_ExceptionHandler = Type.GetType(exceptionHandlerTypeName, true); } } public RestServiceBehavior(Type customBizExceptionType, Type exceptionHandlerType) { m_BizExceptionType = customBizExceptionType; m_ExceptionHandler = exceptionHandlerType; } public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers) { foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints) { endpointDispatcher.DispatchRuntime.MessageInspectors.Insert(0, new RestServiceMessageInspector()); foreach (DispatchOperation dispatchOperation in endpointDispatcher.DispatchRuntime.Operations) { dispatchOperation.ParameterInspectors.Add(new RestServiceParameterInspector()); } } channelDispatcher.ErrorHandlers.Add(new RestServiceErrorHandler()); } } public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } } }RestServiceErrorHandler.cs
namespace H.Utility.WCF { using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel.Dispatcher; using System.ServiceModel; using System.ServiceModel.Channels; using System.Net; using System.ServiceModel.Security; using System.Web; using System.Threading; using System.ServiceModel.Web; using System.Xml; using System.Runtime.Serialization.Json; using System.Runtime.Serialization; using System.Configuration; /// <summary> /// 处理异常 /// </summary> public class RestServiceErrorHandler : IErrorHandler { public void ProvideFault(Exception error, MessageVersion version, ref Message fault) { HttpStatusCode statusCode; if (error is SecurityAccessDeniedException) { statusCode = HttpStatusCode.Unauthorized; } else if (error is ServerTooBusyException) { statusCode = HttpStatusCode.ServiceUnavailable; } else { statusCode = HttpStatusCode.InternalServerError; } RestServiceError errorData = new RestServiceError() { StatusCode = (int)statusCode, StatusDescription = HttpWorkerRequest.GetStatusDescription((int)statusCode), Faults = new List<Error>() }; var errorEntity = new Error(); errorEntity.ErrorCode = "00000"; // errorEntity.ErrorDescription = error.ToString(); errorData.Faults.Add(errorEntity); if (version == MessageVersion.None) { WebMessageFormat messageFormat = WebOperationContext.Current.OutgoingResponse.Format ?? WebMessageFormat.Xml; WebContentFormat contentFormat = WebContentFormat.Xml; string contentType = "text/xml"; if (messageFormat == WebMessageFormat.Json) { contentFormat = WebContentFormat.Json; contentType = "application/json"; } WebBodyFormatMessageProperty bodyFormat = new WebBodyFormatMessageProperty(contentFormat); HttpResponseMessageProperty responseMessage = new HttpResponseMessageProperty(); responseMessage.StatusCode = HttpStatusCode.OK; responseMessage.StatusDescription = HttpWorkerRequest.GetStatusDescription((int)responseMessage.StatusCode); responseMessage.Headers[HttpResponseHeader.ContentType] = contentType; responseMessage.Headers["X-HTTP-StatusCode-Override"] = "500"; fault = Message.CreateMessage(MessageVersion.None, null, new RestServiceErrorWriter() { Error = errorData, Format = contentFormat }); fault.Properties[WebBodyFormatMessageProperty.Name] = bodyFormat; fault.Properties[HttpResponseMessageProperty.Name] = responseMessage; } } class RestServiceErrorWriter : BodyWriter { public RestServiceErrorWriter() : base(true) { } public RestServiceError Error { get; set; } public WebContentFormat Format { get; set; } protected override BodyWriter OnCreateBufferedCopy(int maxBufferSize) { return base.OnCreateBufferedCopy(maxBufferSize); } protected override void OnWriteBodyContents(XmlDictionaryWriter writer) { if (Format == WebContentFormat.Json) { new DataContractJsonSerializer(typeof(RestServiceError)).WriteObject(writer, Error); } else { new DataContractSerializer(typeof(RestServiceError)).WriteObject(writer, Error); } } } public bool HandleError(Exception error) { return true; } } }RestServiceMessageInspector.cs
namespace H.Utility.WCF { using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel.Channels; using System.ServiceModel.Web; using System.ServiceModel.Dispatcher; using System.Security.Cryptography; using H.BizEntity; /// <summary> /// 使用url参数上的数据来修改Get方式时的http头,同时如果有传当前用户信息,还会验证签名,并作授权验证 /// 此方法优先级比IEndpointBehavior 低 /// </summary> public class RestServiceMessageInspector : IDispatchMessageInspector { #region IDispatchMessageInspector Members /// <summary> /// 授权验证 /// </summary> /// <param name="request"></param> /// <param name="channel"></param> /// <param name="instanceContext"></param> /// <returns></returns> public object AfterReceiveRequest(ref Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext) { throw new BizException("未经授权访问..."); return null; } private string GetQueryStringValue(IncomingWebRequestContext context, string key) { try { var queryStrings = context.UriTemplateMatch.QueryParameters; return queryStrings[key]; } catch { return null; } } public void BeforeSendReply(ref Message reply, object correlationState) { HttpResponseMessageProperty response = reply.Properties[HttpResponseMessageProperty.Name] as HttpResponseMessageProperty; response.Headers["Cache-Control"] = "No-Cache"; } #endregion } }
相关文章推荐
- WCF-REST IEndpointBehavior 对Service 监控 用户访问验证
- 关于wcf异常异常信息:由于内部错误,服务器无法处理该请求。有关该错误的详细信息,请打开服务器上的 IncludeExceptionDetailInFaults (从 ServiceBehaviorAttribut
- WCF用户名密码验证——获取准确的用户验证失败异常信息
- 异常信息:由于内部错误,服务器无法处理该请求。有关该错误的详细信息,请打开服务器上的 IncludeExceptionDetailInFaults (从 ServiceBehaviorAttribut
- WCF技术剖析之二十四: ServiceDebugBehavior服务行为是如何实现异常的传播的?
- 【REST】在 WCF RESTfull service 中实现自己的身份验证方式
- 异常信息:由于内部错误,服务器无法处理该请求。有关该错误的详细信息,请打开服务器上的 IncludeExceptionDetailInFaults (从 ServiceBehaviorAttribut
- Effective Error Handling with WCF & REST(WCF REST Service 高效错误处理)
- WCF 构建REST Service 跨域访问解决方法
- 由于内部错误,服务器无法处理该请求。有关该错误的详细信息,请打开服务器上的 IncludeExceptionDetailInFaults (从 ServiceBehaviorAttribute 或从 <serviceDebug> 配置行为)以便将异常信息发送回客户端,
- 0xC0000005:读取某位置发生访问冲突;未处理的异常:用户断点
- II7添加应用程序测试时 无法验证对路径(c:\test\WcfService)的访问
- STS创建Spring Boot项目实战(Rest接口、数据库、用户认证、分布式Token JWT、Redis操作、日志和统一异常处理)
- STS创建Spring Boot项目实战(Rest接口、数据库、用户认证、分布式Token JWT、Redis操作、日志和统一异常处理)
- 异常信息:由于内部错误,服务器无法处理该请求。有关该错误的详细信息,请打开服务器上的 IncludeExceptionDetailInFaults (从 ServiceBehaviorAttribut
- WCF技术剖析之二十四: ServiceDebugBehavior服务行为是如何实现异常的传播的?
- 由于内部错误,服务器无法处理该请求。有关该错误的详细信息,请打开服务器上的 IncludeExceptionDetailInFaults (从 ServiceBehaviorAttribute 或从 <serviceDebug> 配置行为)以便将异常信息发送回客户端,或打开对每个 Microsoft .NET Framework SDK 文档的跟踪并检查服务器跟踪日志。
- 分别用(Windows/Form/Soap/WebService)实现用户身份验证(含示例代码下载)
- 函数用户PHP自学之路----错误及异常处理机制、错误日志
- WCF异常信息:由于内部错误,服务器无法处理该请求