2012-01-17 60 views
5

我有一個asp.net web服務(不是WCF,但帶有WebMethods的經典.asmx)引發異常。例外所有從兩個基異常類(兩者自Exception派生)中的一個導出:如何確定由asp.net Web服務引發的異常類型?

public class InputException : Exception 
{ 
    .... 
} 

public class FatalException : Exception 
{ 
    .... 
} 

public class NoFilesFound: FatalException 
{ 
    .... 
} 

.... 

的web服務需要現在拋出異常。在我的客戶端代碼,我可以捕捉到的異常,看到這樣的消息:

Server was unable to process request. ---> There were no files found

但是異常的類型FaultException異常的(因爲當我做.GetType()上捕捉到的異常所見)。調用客戶端需要能夠區分InputException和FatalException(並且最佳地區分各個派生的派生類,但這並不重要)。現在唯一的方法就是解析消息,在「--->」之前去掉文本並打開文本。這顯然不是最佳的。

我知道我可以拋出SoapExceptions與自定義代碼,但我想避免,如果可能的話。此外,它似乎專爲那些處理XML的人設計,但我們的所有Web服務代碼都不會觸及XML,因爲它已經爲我們反序列化了。

簡而言之,有沒有辦法讓我從Web服務中拋出自定義異常,並讓調用客戶端能夠區分異常?

回答

7

處理此問題的正確方法是使用SoapException。因此,您將基本上捕獲服務上所有可能的異常,然後將它們轉換爲SoapException(我鏈接到的文檔包含一個示例),然後不拋出一些自定義異常拋出SoapException幷包含您感興趣的信息故障的Detail XML節點。

然後,在客戶端上調用服務時,您將能夠捕獲此SoapException並分析Detail XML節點以收集有關服務器上發生的故障的確切原因的更多詳細信息。

在WCF中,所有這些手動生成的故障節點都變得非常簡單,您只需使用數據合同並捕獲FaultException<SomeFaultContract>

舉個例子吧。假如你有一個拋出SOAPException異常,並提供了有關詳細信息節點錯誤的詳細信息如下服務方法:

[WebMethod] 
public string HelloWorld() 
{ 
    var doc = new XmlDocument(); 
    var node = doc.CreateNode(
     XmlNodeType.Element, 
     SoapException.DetailElementName.Name, 
     SoapException.DetailElementName.Namespace 
    ); 
    // you could actually use any sub nodes here 
    // and pass even complex objects 
    node.InnerText = "no files found"; 

    throw new SoapException(
     "Fault occurred", 
     SoapException.ClientFaultCode, 
     Context.Request.Url.AbsoluteUri, 
     node 
    ); 
} 

消費時,你能趕上這個的SoapException在客戶端上:

using (var client = new WebService1()) 
{ 
    try 
    { 
     var result = client.HelloWorld(); 
    } 
    catch (SoapException ex) 
    { 
     var detail = ex.Detail; 
     // detail.InnerText will contain the detail message 
     // as detail is an XmlNode if on the server you have 
     // provided a complex XML you would be able to fetch it here 
    } 
} 

由於就你的InputException,FatalExceptionNoFilesFound例外而言,它們很好,但它們應該留在服務器上。用你的網絡方法抓住它們,並建立一個合適的SoapException,讓客戶端在使用服務時能夠理解。

+0

謝謝!我想知道是否可以使我的自定義類從SoapException派生,然後使用構造函數構建XmlNode ... – user1079591 2012-01-17 21:27:45

+0

@ user1079591,是的,您可以,它實際上是一種非常好的方式。 – 2012-01-17 21:29:28

+0

所以我按照你的建議做了,但是在客戶端代碼中,它並沒有將它作爲SoapException而是作爲System.ServiceModel.FaultException捕獲。在我的代碼中,我有兩個catch塊:一個用於SoapException,一個用於常規異常,並且它總是進入常規異常,並且當我執行異常時。GetType()表示它是System.ServiceModel.FaultException類型。 – user1079591 2012-01-17 21:45:13