2012-02-16 54 views
2

您好我正在創建一個提供JSON和XML的Restful WCF Web服務。我相信在wcf 4中,您可以指定一個錯誤對象,它將以JSON形式向客戶端返回詳細錯誤。有什麼方法可以完全覆蓋這個並返回文本,因此可以完全控制錯誤的格式嗎?錯誤和寧靜WCF

回答

3

是的,你有。 您可以創建自定義錯誤處理程序並執行您的感受。

查看附加的代碼(只需根據需要更改JsonErrorDetails類)。

這是自定義錯誤處理程序:

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中的錯誤)。

這是我的客戶端(我們的自定義代理的一部分)

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); 
       } 
      }); 
    }