分散アプリケーションを開発しています。その中には、検証しなければならないロールとパーミッションのセットがあります。
exceptionをスローするのは良い例です。たとえば、nauthorized access?
それとも、クライアントにメッセージを返送する必要がありますか?
サービス操作では、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"
}
さて、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!");
}
}
basicHTTPBindingを使用していない場合、一般的なDot Net例外をスローすると、サービスクライアントプロキシとサーバーチャネルがフォールト状態になります。これを回避するには、常にFaultException =サービスから...あなたはブロックをキャッチするだけで使用します:
throw new FaultException("Your message to the clients");