web-dev-qa-db-ja.com

WCFサービスの例外のグッドプラクティス

分散アプリケーションを開発しています。その中には、検証しなければならないロールとパーミッションのセットがあります。
exceptionをスローするのは良い例です。たとえば、nauthorized access
それとも、クライアントにメッセージを返送する必要がありますか?

30
marcelo-ferraz

サービス操作では、FaultContractを指定できます。

[OperationContract]
[FaultContract(typeof(MyServiceFault))]
void MyServiceOperation();

MyServiceFaultは、複合型の場合と同様に、DataContractおよびDataMember属性でマークする必要があることに注意してください。

[DataContract]
public class MyServiceFault
{
    private string _message;

    public MyServiceFault(string message)
    {
        _message = message;
    }

    [DataMember]
    public string Message { get { return _message; } set { _message = value; } }
}

サービス側では、次のことができます。

throw new FaultException<MyServiceFault>(new MyServiceFault("Unauthorized Access"));

そして、クライアント側で:

try
{
    ...
}
catch (FaultException<MyServiceFault> fault)
{
    // fault.Detail.Message contains "Unauthorized Access"
}
53
Traxxus

さて、WCFサービス実装メソッドですべての例外をキャッチし、それらをFaultExceptionsとして再スローできます。このようにすることで、選択したメッセージとともにクライアントで例外が再スローされます。

[OperationContract]
public List<Customer> GetAllCustomers()
{
    try
    {
        ... code to retrieve customers from datastore
    }
    catch (Exception ex)
    {
        // Log the exception including stacktrace
        _log.Error(ex.ToString());

        // No stacktrace to client, just message...
        throw new FaultException(ex.Message);
    }
}

予期しないエラーがクライアントに中継されるのを防ぐために、サーバー側のコードで例外インスタンスをスローしないこともお勧めします。代わりに、独自の例外タイプを1つ以上作成して、スローします。そうすることで、予期しないサーバー処理エラーと無効なリクエストなどによりスローされるエラーを区別できます。

public List<Customer> GetAllCustomers()
{
    try
    {
        ... code to retrieve customers from datastore
    }
    catch (MyBaseException ex)
    {
         // This is an error thrown in code, don't bother logging it but relay
         // the message to the client.
         throw new FaultException(ex.Message);
    }
    catch (Exception ex)
    {
        // This is an unexpected error, we need log details for debugging
        _log.Error(ex.ToString());

        // and we don't want to reveal any details to the client
        throw new FaultException("Server processing error!");
    }
}
12
Daniel Persson

basicHTTPBindingを使用していない場合、一般的なDot Net例外をスローすると、サービスクライアントプロキシとサーバーチャネルがフォールト状態になります。これを回避するには、常にFaultException =サービスから...あなたはブロックをキャッチするだけで使用します:

throw new FaultException("Your message to the clients");
2
khaled4vokalz