错误和 Restful WCF [英] Errors and Restful WCF

查看:23
本文介绍了错误和 Restful WCF的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个提供 JSON 和 XML 的 Restful WCF Web 服务.我相信使用 wcf 4,您可以指定一个错误对象,该对象将以 JSON 格式向客户端返回详细错误.有没有办法完全覆盖它并返回文本,从而完全控制错误的格式?

Hi I'm creating a Restful WCF web services that serves up JSON and XML. I believe with wcf 4 you can specify an error object which will return a detailed error to the client in JSON. Is there any way of completely overriding this and return text and therefore have complete control over the format of the error?

推荐答案

是的.您可以创建自定义错误处理程序并按照您的意愿进行操作.

Yes you have. You can create custom error handler and do what you feel like.

查看附加代码(只需根据需要更改 JsonErrorDetails 类).

See the attached code (just change the JsonErrorDetails class as needed).

这是自定义错误处理程序:

public class JsonErrorHandler : IErrorHandler
{

    public bool HandleError(Exception error)
    {
        // Yes, we handled this exception...
        return true;
    }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        // Create message
        var jsonError = new JsonErrorDetails { Message = error.Message, ExceptionType = error.GetType().FullName };
        fault = Message.CreateMessage(version, "", jsonError,
                                      new DataContractJsonSerializer(typeof(JsonErrorDetails)));

        // Tell WCF to use JSON encoding rather than default XML
        var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
        fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);

        // Modify response
        var rmp = new HttpResponseMessageProperty
                      {
                          StatusCode = HttpStatusCode.BadRequest,
                          StatusDescription = "Bad Request",
                      };
        rmp.Headers[HttpResponseHeader.ContentType] = "application/json";
        fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);
    }
}

这是注入错误处理程序的扩展服务行为:

/// <summary>
/// This class is a custom implementation of the WebHttpBehavior. 
/// The main of this class is to handle exception and to serialize those as requests that will be understood by the web application.
/// </summary>
public class ExtendedWebHttpBehavior : WebHttpBehavior
{
    protected override void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        // clear default erro handlers.
        endpointDispatcher.ChannelDispatcher.ErrorHandlers.Clear();

        // add our own error handler.
        endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(new JsonErrorHandler());
        //BehaviorExtensionElement
    }
}

这是一个自定义绑定,因此您可以在 web.config 中对其进行配置

/// <summary>
/// Enables the ExtendedWebHttpBehavior for an endpoint through configuration.
/// Note: Since the ExtendedWebHttpBehavior is derived of the WebHttpBehavior we wanted to have the exact same configuration.  
/// However during the coding we've relized that the WebHttpElement is sealed so we've grabbed its code using reflector and
/// modified it to our needs.
/// </summary>
public sealed class ExtendedWebHttpElement : BehaviorExtensionElement
{
    private ConfigurationPropertyCollection properties;
    /// <summary>Gets or sets a value that indicates whether help is enabled.</summary>
    /// <returns>true if help is enabled; otherwise, false. </returns>
    [ConfigurationProperty("helpEnabled")]
    public bool HelpEnabled
    {
        get
        {
            return (bool)base["helpEnabled"];
        }
        set
        {
            base["helpEnabled"] = value;
        }
    }
    /// <summary>Gets and sets the default message body style.</summary>
    /// <returns>One of the values defined in the <see cref="T:System.ServiceModel.Web.WebMessageBodyStyle" /> enumeration.</returns>
    [ConfigurationProperty("defaultBodyStyle")]
    public WebMessageBodyStyle DefaultBodyStyle
    {
        get
        {
            return (WebMessageBodyStyle)base["defaultBodyStyle"];
        }
        set
        {
            base["defaultBodyStyle"] = value;
        }
    }
    /// <summary>Gets and sets the default outgoing response format.</summary>
    /// <returns>One of the values defined in the <see cref="T:System.ServiceModel.Web.WebMessageFormat" /> enumeration.</returns>
    [ConfigurationProperty("defaultOutgoingResponseFormat")]
    public WebMessageFormat DefaultOutgoingResponseFormat
    {
        get
        {
            return (WebMessageFormat)base["defaultOutgoingResponseFormat"];
        }
        set
        {
            base["defaultOutgoingResponseFormat"] = value;
        }
    }
    /// <summary>Gets or sets a value that indicates whether the message format can be automatically selected.</summary>
    /// <returns>true if the message format can be automatically selected; otherwise, false. </returns>
    [ConfigurationProperty("automaticFormatSelectionEnabled")]
    public bool AutomaticFormatSelectionEnabled
    {
        get
        {
            return (bool)base["automaticFormatSelectionEnabled"];
        }
        set
        {
            base["automaticFormatSelectionEnabled"] = value;
        }
    }
    /// <summary>Gets or sets the flag that specifies whether a FaultException is generated when an internal server error (HTTP status code: 500) occurs.</summary>
    /// <returns>Returns true if the flag is enabled; otherwise returns false.</returns>
    [ConfigurationProperty("faultExceptionEnabled")]
    public bool FaultExceptionEnabled
    {
        get
        {
            return (bool)base["faultExceptionEnabled"];
        }
        set
        {
            base["faultExceptionEnabled"] = value;
        }
    }
    protected override ConfigurationPropertyCollection Properties
    {
        get
        {
            if (this.properties == null)
            {
                this.properties = new ConfigurationPropertyCollection
                {
                    new ConfigurationProperty("helpEnabled", typeof(bool), false, null, null, ConfigurationPropertyOptions.None), 
                    new ConfigurationProperty("defaultBodyStyle", typeof(WebMessageBodyStyle), WebMessageBodyStyle.Bare, null, null, ConfigurationPropertyOptions.None), 
                    new ConfigurationProperty("defaultOutgoingResponseFormat", typeof(WebMessageFormat), WebMessageFormat.Xml, null, null, ConfigurationPropertyOptions.None), 
                    new ConfigurationProperty("automaticFormatSelectionEnabled", typeof(bool), false, null, null, ConfigurationPropertyOptions.None), 
                    new ConfigurationProperty("faultExceptionEnabled", typeof(bool), false, null, null, ConfigurationPropertyOptions.None)
                };
            }
            return this.properties;
        }
    }
    /// <summary>Gets the type of the behavior enabled by this configuration element.</summary>
    /// <returns>The <see cref="T:System.Type" /> for the behavior enabled with the configuration element: <see cref="T:System.ServiceModel.Description.WebHttpBehavior" />.</returns>
    public override Type BehaviorType
    {
        get
        {
            return typeof(ExtendedWebHttpBehavior);
        }
    }
    protected override object CreateBehavior()
    {
        return new ExtendedWebHttpBehavior
        {
            HelpEnabled = this.HelpEnabled,
            DefaultBodyStyle = this.DefaultBodyStyle,
            DefaultOutgoingResponseFormat = this.DefaultOutgoingResponseFormat,
            AutomaticFormatSelectionEnabled = this.AutomaticFormatSelectionEnabled,
            FaultExceptionEnabled = this.FaultExceptionEnabled
        };
    }
}

这就是 web.config

  <system.serviceModel>
<diagnostics>
  <messageLogging logMalformedMessages="true" logMessagesAtTransportLevel="true" />
</diagnostics>
<bindings>
  <webHttpBinding>
    <binding name="regularService" />
  </webHttpBinding>
</bindings>
<behaviors>
  <endpointBehaviors>
    <behavior name="AjaxBehavior">
      <extendedWebHttp />
    </behavior>
  </endpointBehaviors>
  <serviceBehaviors>
    <behavior>
      <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
      <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
      <serviceDebug includeExceptionDetailInFaults="true"/>
    </behavior>
  </serviceBehaviors>
</behaviors>
<extensions>
  <behaviorExtensions>
    <add name="extendedWebHttp" type="MyNamespace.ExtendedWebHttpElement, MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
  </behaviorExtensions>
</extensions>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
  <service name="MyWebService">
    <endpoint address="" behaviorConfiguration="AjaxBehavior"
      binding="webHttpBinding" bindingConfiguration="regularService"
      contract="IMyWebService" />
  </service>
</services>

注意:行为扩展应该按原样在一行中(WCF 中存在一个错误).

Note: The behavior extension should be in one line EXACTLY as is (there's a bug in WCF).

这是我的客户端(我们自定义代理的一部分)

 public void Invoke<T>(string action, object prms, JsAction<T> successCallback, JsAction<WebServiceException> errorCallback = null, JsBoolean webGet = null)
    {
        Execute(new WebServiceRequest { Action = action, Parameters = prms, UseGetMethod = webGet },
            t =>
            {
                successCallback(t.As<T>());
            },
            (req, message, err)=>
            {
                if (req.status == 400) //Bad request - that's what we've specified in the WCF error handler.
                {
                    var details = JSON.parse(req.responseText).As<JsonErrorDetails>();
                    var ex = new WebServiceException()
                    {
                        Message = details.Message,
                        StackTrace = details.StackTrace,
                        Type = details.ExceptionType
                    };

                    errorCallback(ex);
                }
            });
    }

这篇关于错误和 Restful WCF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆