C#为WCF服务实现IErrorHandler

示例

为WCF服务实现IErrorHandler是集中错误处理和日志记录的好方法。此处显示的实现应捕获由于调用您的WCF服务之一而引发的任何未处理的异常。此示例还显示了如何返回自定义对象,以及如何返回JSON而不是默认XML。

实现IErrorHandler:

using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Runtime.Serialization.Json;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace BehaviorsAndInspectors
{
    public class ErrorHandler : IErrorHandler
    {

        public bool HandleError(Exception ex)
        {
            // 在这里记录例外

            return true;

        } // 结束

        public void ProvideFault(Exception ex, MessageVersion version, ref Message fault)
        {
            // 获取当前上下文的传出响应部分
            var response = WebOperationContext.Current.OutgoingResponse;

            // 设置默认的http状态代码 
           response.StatusCode= HttpStatusCode.InternalServerError;

            // 添加指定我们正在使用JSON的ContentType标头
           response.ContentType= new MediaTypeHeaderValue("application/json").ToString();

            // 使用BaseDataResponseContract创建返回的故障消息(注意ref参数)                
            fault = Message.CreateMessage(
                version,
                string.Empty,
                new CustomReturnType { ErrorMessage = "发生未处理的异常!" },
                new DataContractJsonSerializer(typeof(BaseDataResponseContract), new List<Type> { typeof(BaseDataResponseContract) }));

            if (ex.GetType() == typeof(VariousExceptionTypes))
            {
                 // 您可能想在这里捕获不同类型的异常,并以不同的方式处理它们
            }

            // 告诉WCF使用JSON编码而不是默认XML
            var webBodyFormatMessageProperty = new WebBodyFormatMessageProperty(WebContentFormat.Json);
            fault.Properties.Add(WebBodyFormatMessageProperty.Name, webBodyFormatMessageProperty);

        } // 结束

    } // 结束 class

} // 结束 namespace

在此示例中,我们将处理程序附加到服务行为。您也可以通过类似的方式将此附加到IEndpointBehavior,IContractBehavior或IOperationBehavior。

附加到服务行为:

using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

namespace BehaviorsAndInspectors
{
    public class ErrorHandlerExtension : BehaviorExtensionElement, IServiceBehavior
    {
        public override Type BehaviorType
        {
            get { return GetType(); }
        }

        protected override object CreateBehavior()
        {
            return this;
        }

        private IErrorHandler GetInstance()
        {
            return new ErrorHandler();
        }

        void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { } // 结束

        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            var errorHandlerInstance = GetInstance();

            foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
            {
                dispatcher.ErrorHandlers.Add(errorHandlerInstance);
            }
        }

        void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } // 结束
      
    } // 结束 class

} // 结束 namespace

Web.config中的配置:

...
<system.serviceModel>

    <services>      
      <service name="WebServices.MyService">
        <endpoint binding="webHttpBinding" contract="WebServices.IMyService" />
      </service>
    </services>

    <extensions>      
      <behaviorExtensions>        
        <!-- This extension if for the WCF Error Handling-->
        <add name="ErrorHandlerBehavior" type="WebServices.BehaviorsAndInspectors.ErrorHandlerExtensionBehavior, WebServices, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />      
      </behaviorExtensions>    
    </extensions>

    <behaviors>          
      <serviceBehaviors>        
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <ErrorHandlerBehavior />
        </behavior>     
      </serviceBehaviors>    
    </behaviors>

    ....
</system.serviceModel>
...

这里有一些链接可能对该主题有所帮助:

https://msdn.microsoft.com/zh-CN/library/system.servicemodel.dispatcher.ierrorhandler(v=vs.100).aspx

http://www.brainthud.com/cards/5218/25441/which-four-behavior-interfaces-exist-for-interacting-with-a-service-or-client-description-what-methods-do-they-实施和

其他例子:

HTTP状态代码为401时,IErrorHandler返回错误的消息正文

IErrorHandler似乎没有处理WCF中的错误。

如何使自定义WCF错误处理程序以非OK HTTP代码返回JSON响应?

如何设置HttpClient请求的Content-Type标头?