1. ホーム
  2. c#

[解決済み] ASP.NET Web APIでエラーを返すためのベストプラクティス

2022-03-22 01:28:49

質問

クライアントにエラーを返す方法について懸念していることがあります。

を投げて、すぐにエラーを返すのか? HttpResponseException というエラーが発生しました。

public void Post(Customer customer)
{
    if (string.IsNullOrEmpty(customer.Name))
    {
        throw new HttpResponseException("Customer Name cannot be empty", HttpStatusCode.BadRequest) 
    }
    if (customer.Accounts.Count == 0)
    {
         throw new HttpResponseException("Customer does not have any account", HttpStatusCode.BadRequest) 
    }
}

あるいは、すべてのエラーを蓄積して、クライアントに送り返す。

public void Post(Customer customer)
{
    List<string> errors = new List<string>();
    if (string.IsNullOrEmpty(customer.Name))
    {
        errors.Add("Customer Name cannot be empty"); 
    }
    if (customer.Accounts.Count == 0)
    {
         errors.Add("Customer does not have any account"); 
    }
    var responseMessage = new HttpResponseMessage<List<string>>(errors, HttpStatusCode.BadRequest);
    throw new HttpResponseException(responseMessage);
}

これは単なるサンプルコードで、バリデーションエラーもサーバーエラーも関係ありません。ただ、ベストプラクティス、それぞれのアプローチの長所と短所を知りたいのです。

どのように解決するのですか?

私の場合、通常 HttpResponseException を送信するかどうかは、スローされた例外に応じてステータスコードを設定し、その例外が致命的かどうかで決まります。 HttpResponseException をすぐに実行します。

結局はAPIがレスポンスを返しているのであって、ビューではないので、例外とステータスコードを含むメッセージをコンシューマに送り返しても問題ないと思います。私は今のところ、ほとんどの例外は間違ったパラメータや呼び出しなどによるものなので、エラーを蓄積して送り返す必要はありません。

私のアプリの例では、クライアントがデータを要求してくることがありますが、利用可能なデータがないため、私はカスタム NoDataAvailableException で、それを Web API アプリにバブリングさせ、カスタムフィルターでそれを捕捉して、正しいステータスコードとともに関連するメッセージを送り返すのです。

何がベストプラクティスなのか100%わかっているわけではありませんが、今のところこれがうまくいっているので、そうしています。

更新情報 :

この質問に答えてから、この話題についていくつかのブログ記事が書かれました。

https://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling

(こちらはナイトリービルドでいくつかの新機能が追加されています) https://docs.microsoft.com/archive/blogs/youssefm/error-handling-in-asp-net-webapi

アップデート2

エラー処理プロセスのアップデート、2つのケースがあります。

  1. 見つからない、アクションに渡されたパラメータが無効などの一般的なエラーの場合、我々は HttpResponseException を実行し、直ちに処理を停止する。さらに、アクションのモデルエラーの場合、モデルステート辞書を Request.CreateErrorResponse 拡張モジュールでラップし HttpResponseException . モデル状態辞書を追加すると、レスポンスボディに送信されるモデルエラーのリストが表示されます。

  2. 上位レイヤーで発生したエラー、サーバーエラーについては、例外を Web API アプリにバブリングさせます。ここでは、グローバル例外フィルタを使用して例外を調べ、ELMAH でログを記録し、正しい HTTP ステータスコードと関連するフレンドリーなエラーメッセージをボディとして設定しようとします。 HttpResponseException . 私たちが想定していない例外については、クライアントはデフォルトの500 internal server errorを受け取りますが、セキュリティ上の理由から一般的なメッセージが表示されます。

アップデート3

最近、Web API 2 を導入したことで、一般的なエラーの返送に IHttpActionResult インターフェース、特に System.Web.Http.Results 名前空間の NotFound や BadRequest が適切な場合はそれらを拡張し、そうでない場合は例えば NotFound の結果を応答メッセージで返すようにします。

public class NotFoundWithMessageResult : IHttpActionResult
{
    private string message;

    public NotFoundWithMessageResult(string message)
    {
        this.message = message;
    }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        var response = new HttpResponseMessage(HttpStatusCode.NotFound);
        response.Content = new StringContent(message);
        return Task.FromResult(response);
    }
}