メインコンテンツまでスキップ

例外のハンドリングとステータスコード

MagicOnion ではサーバーの処理結果を戻り値とは別にステータスコードとして返す仕組みがあります。これは HTTP のステータスコードや gRPC のステータスコードと同様です。このステータスコードにはアプリケーション固有のステータスコードを含めることもできます。

サーバーからクライアントへのステータスコードの通知

サーバーからクライアントへカスタムステータスコードを返す場合は ReturnStatusException を使用できます。

public Task SendMessageAsync(string message)
{
if (message.Contains("foo"))
{
//
throw new ReturnStatusException((Grpc.Core.StatusCode)MyStatusCode.SomethingWentWrong, "invalid");
}

// ....

ReturnStatusException はステータスコードである Grpc.Core.StatusCode 列挙型を持ち、この値をクライアントへ通知します。アプリケーションのカスタムステータスコードを返すには独自の int 値または列挙型を Grpc.Core.StatusCode 列挙型にキャストしてください。

例外のスローを避けるためにパフォーマンスを重視する場合は CallContext.Status (ServiceContext.CallContext.Status) を使用してステータスを直接設定できます。

クライアントでの例外ハンドリング

クライアントではメソッド呼び出し時の例外はすべて gRPC の RpcException として受信されます。

var client = MagicOnionClient.Create<IGreeterService>(channel);
try
{
var result = await client.SayHelloAsync("Alice", 18);
}
catch (RpcException ex)
{
// handle exception ...
if (((MyStatusCode)ex.Status.StatusCode) == MyStatusCode.SomethingWentWrong)
{
// ...
}
}

ネットワークに問題がある場合は RpcExceptionStatusCode.Unavailable でスローされます。詳しいエラー内容は InnerException プロパティーで調査できます。

サーバー上での未処理の例外

サーバーのメソッド呼び出し中にエラーが発生し ReturnStatusException を除くハンドルされない例外がスローされた場合、クライアントでは StatusCode.Unknown がセットされた RpcException として取り扱われます。

この際 MagicOnionOption.IsReturnExceptionStackTraceInErrorDetailtrue の場合、クライアントはサーバーの例外のスタックトレースを受信できます。デバッグには非常に便利ですがセキュリティ上の重大な問題があるためデバッグビルドでのみ有効にする必要があります。