WCFREST服务集中异常处理抛出json格式的异常消息

最近项目需要和APP对接或者第三方平台,开放接口所以我选择WCF REST服务配置如下:

WCF接口:

WCF实现:

下面是Web.config配置

 <system.serviceModel>
    <bindings>
      <!--webHttpBinding 绑定-->
      <webHttpBinding>        
        <binding name="NewBindingName"  allowCookies="true"  crossDomainScriptAccessEnabled="true" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00"
                 sendTimeout="00:01:00" transferMode="Buffered" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="2147483647" maxBufferSize="2147483647"
                 maxReceivedMessageSize="2147483647">
          <readerQuotas maxDepth="32" maxStringContentLength="819200000" maxArrayLength="163840000" maxBytesPerRead="4096000" maxNameTableCharCount="16384000" />
          <security mode="None">
            <transport clientCredentialType="Windows" />
          </security>
        </binding>
      </webHttpBinding>
      <!--【结束】webHttpBinding 绑定-->
    </bindings>
    <services>
      <!--终结点 DrpService WCF接口服务{DRP对接接口配置}-->
      <service name="PBDealerAPPWCF.DRPInterface.DrpService" behaviorConfiguration="serviceBehaviorsName">
        <endpoint contract="PBDealerAPPWCF.DRPInterface.IDrpService"  address=""  behaviorConfiguration="endpointName" binding="webHttpBinding" bindingConfiguration="NewBindingName" kind="webHttpEndpoint" endpointConfiguration="RESTEndpoint" />
      </service>
    </services>
    <behaviors>
      <!--【结束】服务行为 serviceBehaviorsName-->
      <serviceBehaviors>
        <behavior name="serviceBehaviorsName">
          <serviceThrottling maxConcurrentCalls="1000" maxConcurrentSessions="10000" maxConcurrentInstances="1000" />
          <dataContractSerializer maxItemsInObjectGraph="2147483647" />
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
        <!--【结束】服务行为 serviceBehaviorsName-->
<!--默认:服务行为--> <behavior> <serviceThrottling maxConcurrentCalls="1000" maxConcurrentSessions="10000" maxConcurrentInstances="1000" /> <dataContractSerializer maxItemsInObjectGraph="2147483647" /> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> <!--【结束】默认:服务行为--> </serviceBehaviors> <endpointBehaviors> <!--【结束】终结点 endpointName--> <behavior name="endpointName"> <webHttp helpEnabled="true" automaticFormatSelectionEnabled="true" /> <dataContractSerializer maxItemsInObjectGraph="6553500" /> </behavior> <!--【结束】终结点 endpointName--> </endpointBehaviors> </behaviors> <protocolMapping> <add binding="basicHttpsBinding" scheme="https" /> </protocolMapping> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> </system.serviceModel>

要想实现集中异常处理需要在整个服务内修改或插入自定义扩展的机制,Attribute, IServiceBehavior,我里面RetMessageSig是我自己封装返回消息实体,做一个统一的返回对象,而返回消息格式是Json的,告诉WCF使用JSON编码而不是默认的XML ;WebBodyFormatMessageProperty wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);来控制告诉WCF,然后序列化,每次都不会进异常返回给前端,而我向前端传输都不会是400,500,等等,都是200成功的,失败都是在RetMessageSig 里面model.RetCode = DFMSMPRetMsgFactory.ExceptionCode.失败.GetHashCode();来告诉前端具体出错内容。 // 返回自定义错误码, 500. rmp.StatusCode = HttpStatusCode.OK;

  /// <summary>
    /// 实现(IServiceBehavior):提供一种在整个服务内修改或插入自定义扩展的机制,包括 System.ServiceModel.ServiceHostBase。
    /// </summary>
    public class GlobalExceptionHandlerBehaviourAttribute : Attribute, IServiceBehavior
    {
        /// <summary>
        /// 使用指定类型的默认构造函数来创建该类型的实例。
        /// </summary>
        private readonly Type _errorHandlerType;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="errorHandlerType">使用指定类型的默认构造函数来创建该类型的实例。</param>
        public GlobalExceptionHandlerBehaviourAttribute(Type errorHandlerType)
        {
            _errorHandlerType = errorHandlerType;
        }

        #region IServiceBehavior Members

        /// <summary>
        /// 用于向绑定元素传递自定义数据,以支持协定实现。
        /// </summary>
        /// <param name="description">服务的服务说明。</param>
        /// <param name="serviceHostBase">服务的主机。</param>
        /// <param name="endpoints">服务终结点。</param>
        /// <param name="parameters">绑定元素可访问的自定义对象。</param>
        public void AddBindingParameters(ServiceDescription description,
                                         ServiceHostBase serviceHostBase,
                                         Collection<ServiceEndpoint> endpoints,
                                         BindingParameterCollection parameters)
        {
        }

        /// <summary>
        /// 用于更改运行时属性值或插入自定义扩展对象(例如错误处理程序、消息或参数拦截器、安全扩展以及其他自定义扩展对象)。
        /// </summary>
        /// <param name="description">服务说明。</param>
        /// <param name="serviceHostBase">当前正在构建的服务宿主。</param>
        public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
        {
            var handler = (IErrorHandler)Activator.CreateInstance(_errorHandlerType);

            foreach (ChannelDispatcherBase dispatcherBase in serviceHostBase.ChannelDispatchers)
            {
                var channelDispatcher = dispatcherBase as ChannelDispatcher;
                if (channelDispatcher != null)
                {
                    channelDispatcher.ErrorHandlers.Add(handler);
                }
            }
        }

        /// <summary>
        /// 用于检查服务宿主和服务说明,从而确定服务是否可成功运行。
        /// </summary>
        /// <param name="description">服务说明。</param>
        /// <param name="serviceHostBase">当前正在构建的服务宿主。</param>
        public void Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
        {
        }

        #endregion IServiceBehavior Members
    }
   /// <summary>
    /// WCF服务端异常处理器(DRP对接和金蝶对接)
    /// </summary>
    public class WCF_ExceptionHandlerDRPInterface : IErrorHandler
    {
        #region IErrorHandler Members

        /// <summary>
        ///  启用错误相关处理并返回一个值,该值指示调度程序在某些情况下是否中止会话和实例上下文。
        /// </summary>
        /// <param name="ex">处理过程中引发的异常。</param>
        /// <returns>true</returns>
        public bool HandleError(Exception ex)
        {
            return true;
        }

        /// <summary>
        ///  启用创建从服务方法过程中的异常返回的自定义 System.ServiceModel.FaultException`1。
        /// </summary>
        /// <param name="ex">服务操作过程中引发的 System.Exception 对象。</param>
        /// <param name="version">消息的 SOAP 版本。</param>
        /// <param name="msg">双工情况下,返回到客户端或服务的 System.ServiceModel.Channels.Message 对象。</param>
        public void ProvideFault(Exception ex, MessageVersion version, ref Message msg)
        {

            RetMessageSig model=new RetMessageSig();
            model.RetCode = DFMSMPRetMsgFactory.ExceptionCode.失败.GetHashCode();
            model.RetMsg = ex.Message;

            //添加将要返回的异常信息
            msg = Message.CreateMessage(version, "", model, new DataContractJsonSerializer(typeof(RetMessageSig)));

            //告诉WCF使用JSON编码而不是默认的XML
            WebBodyFormatMessageProperty wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);

            //添加格式化程序故障。
            msg.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);

            //修改响应
            HttpResponseMessageProperty rmp = new HttpResponseMessageProperty();

            // 返回自定义错误码, 500.
            rmp.StatusCode = HttpStatusCode.OK;

            //rmp.StatusDescription = "Bad request";

            //Headers写入jsonerror和JSON内容( Content-Type 标头,指定伴随正文数据的 MIME 类型。)
            rmp.Headers[HttpResponseHeader.ContentType] = "application/json";
            rmp.Headers[HttpResponseHeader.ContentEncoding] = "utf-8";
            //rmp.Headers["jsonerror"] = "true";

            //添加到故障
            msg.Properties.Add(HttpResponseMessageProperty.Name, rmp);

        }

        #endregion IErrorHandler Members
    }

这样就实现异常拦截,只需要在WCF实现位置使用,我们刚才新增的GlobalExceptionHandlerBehaviour和WCF_ExceptionHandlerDRPInterface就可以了

 希望对大家有用,有问题可以联系我QQ1412810457,第一次写博客,写得不好请大家多多指导,谢谢!

posted @ 2017-05-03 21:23  GMjh  阅读(699)  评论(0)    收藏  举报