2012-01-17 9 views
5

私は例外をスローするasp.NET Webサービス(WCFではなく、WebMethodsでの.asmx)を持っています。例外はすべて(Exceptionから派生どちらも)2つのベース例外クラスのいずれかから派生: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をスローして、障害の詳細XMLノード

クライアントでサービスを呼び出すと、このSoapExceptionをキャッチし、詳細XMLノードを分析して、サーバーで発生したフォールトの正確な理由を詳細に収集できます。

WCFでは、この手動での障害ノードの生成はすべて、簡単にレンダリングされ、データコントラクトを使用してFaultException<SomeFaultContract>をキャッチします。

例を考えてみましょう。あなたはthrows 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 
    ); 
} 

それを消費するときには、クライアント上でこのthrows 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 
    } 
} 

として、あなたのInputExceptionFatalException、およびNoFilesFoundの例外に関しては問題ありませんが、サーバー上に留まるべきです。あなたのウェブメソッドでそれらをキャッチし、クライアントがサービスを消費するときに意味をなけることができる適切なSoapExceptionを構築します。

+0

ありがとうございました!私は私のカスタムクラスをSoapExceptionから派生させてから、コンストラクタを使ってXmlNodesを構築できるのだろうかと疑問に思うでしょう。 – user1079591

+0

@ user1079591はい、できます。それは実際には非常に良い方法です。 –

+0

だから私はあなたが示唆したように、クライアントコードではSoapExceptionとしてキャッチしていませんが、System.ServiceModel.FaultExceptionとしてキャッチしています。私のコードでは、私は2つのキャッチブロックを持っています:1つはSoapException用、もう1つは通常のException用です。ジェネリック型のGetType()は、System.ServiceModel.FaultException型であることを示します。 – user1079591

関連する問題