2017-10-07 12 views
-1

意味のあるHTTP応答を返すことをお勧めしますが、これを処理するための正しいアプローチを考え出しています。ASP.NET Core 2.0 Web APIで意味のあるHTTP応答を返す

私のASP.NET Core Web APIアプリケーションでは、エンドポイント、つまりAPIアクションメソッドはリクエストを受信し、レスポンスのためにビジネスレイヤを呼び出して応答を返します。

ビジネスレイヤでは、要求が承認されているかどうかを確認します。許可されていない場合は、例外の種類、つまり許可されていないリクエストを表す例外がスローされますが、APIエンドポイントではHTTP 500が返されます。私はむしろHTTP 401を返すだろう。

質問は下位レベルの例外をステータスコードHTTPに転送する方法です。

つの質問:

  1. それはアプリで低いレベルで発生した例外の種類をキャプチャし、HTTP応答にそれを翻訳しようとしようとしている価値があるか、私は単に私のAPIがHTTP 500を返させてください?
  2. もしそれが価値があるのであれば、どうすればいいですか?
+0

5xxと4xxとの対話とエラーメッセージの応答が間違っています。 –

+0

@Sam - 私はAlexeiに同意します。しかし、もしあなたがそれをやるべきではなく、どうやってそれをするのかを質問する言葉を言い直すならば、これは合理的な質問でしょう。 – NightOwl888

答えて

1

コントローラがMicrosoft.AspNet.MVC.Controllerを継承していると仮定すると、OK、Forbidden、BadRequest、ObjectResultなどのように必要な処理を継承します。上記の場合あなたは

public async IActionResult DoMyThing() 
{ 
    try 
    { 
     return ObjectResult(await DoMyInternalCall()); 
    } 
    catch (Exception e) 
    { 
     //FigureOut the Exception type indications a security violation 
     return Forbidden() 
    } 
    .... 

は個人的に私は、特に今、我々はタプルを持っていることを、このすべてのビットクリーンになり、例外を投げるのではなく、ステータスを返すAPIを構築することを好む

ような何かを行うことができます。だから何かのように

public async IActionResult DoMyThing() 
{ 
     var (Status status, string myThing) = await DoMyInternalCall(); 
     switch(status) 
     { 
      case Status.OK: return ObjectResult(myThing); 
          break; 

      case Status.AccessDenied: return Forbidden(); 
             break; 

      case Status.NotFound: return Notfound(); 

      ... 

それはちょうど味のことですが - 私は判断しません。要点は、Microsoft.AspNet.MVC.Controllerには、有効なHTTPステータスコードとデータを返すためのメソッドが組み込まれている点です。

+0

これは私が探していたものです。ありがとうございました! – Sam

0

もちろん、リクエストが正しく処理できないということは、必ずしも500内部サーバーエラーであるとは限りません。誰かが存在しないオブジェクトへの更新を要求したらどうなるでしょうか?それは500の範囲に収まらないでしょう(正確にはわかりませんが、4xxというのは推測できますが、これに取り組んでいる間は一般的なHTTP応答の便利なリストが推奨されます)。私は一般に、500年代は「ああ、何かが終わりに起こったし、何がわからないのか」と感じている。ほとんどの場合、より適切な対応があります。

これは、例外が最上位層に向かって移動するにつれて例外が最も一般化されると感じています。 Entity Frameworkはいくつかの難解な例外をスローします。データアクセスレイヤーは、より一般的なDataAccessException(元のものはもちろん内部のもの)でラップしますが、リポジトリはそれをさらに一般的に処理し、コントローラに到達するまでに応答処理のためには、処理する必要がある「実際の」例外をほんの一握りしか持たないようにしてください。かなり一般的なものを返し、サーバー上でネストされた例外を記録し、そこから移動しますか?

マイ2cents

0

のWeb APIは500ステータスコード(内部サーバーエラー)を返さないように努力すべきです。そうであれば、あなたが書いたコードに何か問題があります。

ステータスコードを返すという意図を持つ例外を投げてはいけません。つまり、ブランケットキャッチをすべて行い、いくつかの素晴らしいステータスコードでマスクすることです。クライアントに送信します。

要求にすべての検証とロジックを実行して、4xxステータスコードのいずれかを選択して返送する必要があります。あなたが本当に例外を持っている場合

基本的には、ウェブAPIのステータスコードは、しかし

2XX -- Success //(ex: OK, created, no content, etc) 
3XX -- Redirection //(ex: renamed an API's path/url to a new one) 
4XX -- Client Error 
     ex: 
      405 //Method Not Allowed (ex: client sent a DELETE request to your API) 
      409 //Conflict 
      415 //Unsupported Media Type (ex: client requests for XML -- yuck! no!) 
      416 //Range Not Suitable (ex: client asked for a million records) 
      422 //Unpronounceable Entity (ex: client sent something invalid in the body) 
5XX -- Server Error //(ex: a well written Web API will NEVER error!) 

する必要があり、その後、500エラーコードが正しいです - あなたが悪いのコードを書いたことを意味し(私の最初のポイントに戻って参照してください)。

+0

あなたは、ユーザーがビジネス層ではなくAPIレベルで承認されているかどうかを確認する必要がありますか? – Sam

+0

@Sam提供された情報に基づいて確かめることはできませんが、実際にはすべてのレイヤーで検証する必要があります。レイヤー間のデータが有効であるとは決して決してしないでください。 – Svek

+0

@Sam一般的に早く**悪いリクエスト**を止めることができます。リクエストパイプラインを下にして(各レイヤーをさらに下へ)進む方が良いでしょう。ほとんどの例外が最初に起きる可能性は低いという意味です。 – Svek

0

私は例外を投げるこのアイディアがまったく好きではありません。 500は、あなた自身のコードで本当に間違っていることの兆候です。

それでは、あなたのビジネス層は、ユーザが許可されているかどうかをチェックしているとしましょう。私がやることは、認可をチェックするメソッドを作成し、そのメソッドが単純なブール型の応答を返すようにすることです。コントローラがフラグをチェックし、偽であれば401を返します。これは、ビジネスレイヤーとAPIレイヤーの間のより良いコミュニケーション方法です。

明らかに、私はあなたのビジネス層がどのように構築されているかを知る方法がありませんが、シンプルに保つ、明確に保つ、例外をトラップしない、すべてをきれいに扱い、

ビジネス層は基本的に、これはあなたがどこでも抽象化が漏れていない、あなたは、彼らが属している層で物事を保つ意味、HTTPコードを扱うべきではありません、APIについては全く気にしてはいけません。

関連する問題