2011-08-25 25 views
16

我有使用IErrorHandler一組被包裝異常的SOAP Web服務的,具體是:WCF IErrorHandler到的FaultException返回SOAP和WebHttpException到POX和JSON的端點

public sealed class ErrorHandler : IErrorHandler 
{ 
    public bool HandleError(Exception error) 
    { 
     return true; 
    } 

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
    { 
     // don't wrap existing fault exceptions 
     if ((error is FaultException)) return; 

     // our basic service fault 
     var businessFault = new BusinessFault { FaultMessage = error.Message, FaultReference = "Internal" }; 

     // Resource based faultReason 
     var faultReason = new FaultReason(Properties.Resources.BusinessFaultReason); 
     var faultcode = FaultCodeFactory.CreateVersionAwareSenderFaultCode(InternalFaultCodes.BusinessFailure.ToString(), Service.Namespace); 

     var faultException = new FaultException<BusinessFault>(
      businessFault, 
      faultReason, 
      faultcode); 

     // Create message fault 
     var messageFault = faultException.CreateMessageFault(); 

     // Create message using Message Factory method 
     fault = Message.CreateMessage(version, messageFault, faultException.Action); 
    } 
} 

我現在已經增加了額外的端點JSON和痘哪些工作正常,除非發生異常。在Json端點的情況下,FaultException作爲XML返回。

我知道從其他等職位,在靜止情況下,我會更好投擲WebHttpException:

throw new WebFaultException<BusinessFault>(detail, HttpStatusCode.BadRequest); 

或者在ProvideFault重寫響應消息的屬性,即:

var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json); 
fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf); 

var rmp = new HttpResponseMessageProperty 
{ 
    StatusCode = System.Net.HttpStatusCode.BadRequest, 
    StatusDescription = "See fault object for more information." 
}; 
fault.Properties.Add(HttpResponseMessageProperty.Name, rmp); 

但是,MSDN有一些關於WebHttpException的有趣評論,即:

當你唱一個WCF REST端點(WebHttpBinding和WebHttpBehavior或WebScriptEnablingBehavior),響應的HTTP狀態碼相應地設置爲 。但是,WebFaultException可以與非REST端點一起使用,其行爲與常規的FaultException類似。

當使用WCF REST端點時,序列化的 故障的響應格式與非故障響應的確定方式相同。有關WCF REST格式的更多 信息,請參閱WCF REST格式。

因此建議我需要轉換當前的ProvideFault方法以提供新的WebHttpException(包裝任何現有的Exception或FaultExceptions),然後SOAP仍然可以正常工作。

是否有人想刺探看起來像什麼(.Net4.0 btw)?我想要一個錯誤處理程序來統治它們!

+0

我不明白你的問題。您是否想要爲JSON/POX/SOAP端點具有唯一的IErrorHandler實現? – Cybermaxs

+1

@Cyber​​maxs正確。 WCF允許您將多個端點公開給不同類型的客戶端。這一切都很好,直到你需要提出錯誤。如果我(一般)提出SOAP錯誤,那麼HTTP客戶端將不會更聰明。如果我提出一個HTTP錯誤,那麼SOAP客戶端將被置於黑暗中。 – Junto

回答

0

我的印象是,使用webHttpBinding是一種方式來獲得JSON/POX/SOAP的「全合一」的功能,而不是使用用於每個單獨的綁定(即wsHttpBindingbasicHttpBinding等)。所以你不能僅僅拋出WebHttpException,然後不管技術如何,都能給你所有你需要的錯誤細節?

0

在我正在處理的REST應用程序中,我創建了一個衍生自WebFaultException<T>的新類,它將一些附加數據附加到捕獲的服務異常。在派生類的實例上調用CreatingMessageFault()方法讓我從錯誤處理程序的ProvideFault()方法返回我選擇的異常數據作爲SOAP錯誤,讓WCF確定正確的消息格式。

我使用webHttpBinding來綁定除一些第三方服務以外的所有服務。

編輯:添加代碼示例

public class ErrorHandler : IErrorHandler, IServiceBehavior 
{  
    public virtual void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
    { 
     // Include next level of detail in message, if any. 
     MyFaultException myFaultException = 
      ((error is MyFaultException) && 
       ((MyFaultException)error).Detail != null) 
      ? new MyFaultException(error.Message + " - " + 
        ((MyFaultException)error).Detail.Message, error) 
      : new MyFaultException(error.Message, error); 
     MessageFault messageFault = myFaultException.CreateMessageFault(); 
     fault = Message.CreateMessage(version, messageFault, myFaultException.Action); 
    } 
} 

/// <summary> 
/// Class used to return exception data from my WCF services. 
/// </summary> 
/// <remarks> 
/// This class is used by a web service to pass exception data back and a 
/// data object to the client. This class inherits WebFaultException, which 
/// is handled specially by the WCF WebServiceHost2 service class and 
/// generates a WebException on the client. 
/// </remarks> 
public class MyFaultException : WebFaultException<BusinessFault> 
{ 
public class MyFaultException : WebFaultException<BusinessFault> 
{ 
    public MyFaultException(string message) 
     : this(HttpStatusCode.BadRequest, message) { } 

    public MyFaultException(HttpStatusCode statusCode, string message) 
     : base(new BusinessFault(message), statusCode) { } 
} 
在服務

那麼,你可以拋出異常故障數據傳遞到客戶端:

 try 
     { 
      // Successful operation proceeds normally. 
     } 
     catch (ApplicationException e) 
     { 
      // Failure generates MyFaultException. 
      throw new MyFaultException("Operation failed with " + e.Message); 
     } 
+0

如果你想添加一個代碼示例,我將能夠嘗試你所描述的。 – Junto

+0

我編輯了我的答案以包含一些示例代碼。 – Suncat2000

+0

我會嘗試找一些時間來嘗試一下。那麼我會很樂意爲你解答這個問題。這可能需要一段時間,因爲我還沒有在這個項目上工作過一段時間! – Junto

相關問題