19

jQuery AJAX ポストを受信し、サードパーティ サービスへの Web サービス リクエストをフォーマットし、結果を消費する .NET .ashx ハンドラがあります。成功すると、関連情報を含む匿名オブジェクトをインスタンス化し、JSON 応答文字列をフォーマットします。

Web サービス エラーが発生した場合、次のことを行います。

context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.StatusDescription = wsResult.ErrorCode;

これにより、jQuery AJAX エラー コールバックからステータス コードと説明の両方に簡単にアクセスできるようになります。ただし、これを実装した方法は非常に恣意的です。

いくつか読んだ後、次の質問に対する決定的な答えを見つけることができません: JSON ベースの AJAX 呼び出しにエラー状態を返すための、受け入れられた普遍的な規則 (または -仕様) はありますか?何を期待するか、またはこれは他の関数呼び出しの戻り値の型と同じくらい恣意的ですか?

それで、これはAJAX呼び出し元にエラーステータスを返す完全に受け入れられる方法ですか、それともJSONエラー応答をフォーマットする「適切な」方法はありますか?

4

5 に答える 5

20

他の人が言ったように、普遍的な慣習はありません。REST の「コミュニティ」は、このような問題について何らかの合意を得る過程にあり、合意が得られない可能性があります。いくつかの例を挙げると:

ステータス コード

デフォルトでは、広く使用されている C# REST ライブラリWeb サービス フレームワークである ServiceStack.NET は、オブジェクト (または空の応答) を状態コードと共に返します。

201 Created

または:

200 OK

検証エラー (例: ArgumentException)の場合、次のようになります。

400 Bad Request

そして、ここですでに物事が変化し始める最初のポイントです。400検証エラーなどのステータス コードを好む人もいれば、好まない人もいます。実際には、リクエスト形式自体の400不正な構文を示しているからです。

HTTP プロトコルの WebDAV 拡張である検証エラーを好む人も422 Unprocessable Entityいますが、それでも技術的には完全に許容できます。

他の人は、HTTP プロトコルで使用されていないエラー ステータス コードの 1 つを取るべきだと考えています461。Twitter は、(とりわけ)420 Enhance Your Calmレート制限されていることをクライアントに通知するために、(表面的には)受け入れられる (そして推奨される) ステータス コード429 Too Many Requestsが既に存在していても、それを行っています。

などなど、すべて哲学の問題です。

について500 Internal Server Errorも同じことが当てはまります - すべての種類のエラー応答に対して完全に問題ないと考える人もいれば、エラーは例外でのみ5xx返されるべきだと考える人もいます (本当の意味で - つまり、例外的なエラー)。エラーが本当に例外的なものである場合、ほとんどの場合、実際の例外情報を渡す機会がなく、サーバーについて多くのことが明らかになる可能性があります。

JSON の結果で何を (もしあれば) 返すべきか? 同じこと...

応答

200 OKエラーが発生しなければ、たとえばリソースを削除する要求に応答するのに十分な場合があります。同様に、404 Not Found削除するエンティティが見つからなかったため、要求された削除を実行できなかったことをクライアントに伝えるだけで十分です。それ以外の場合は、それ以上が必要になる場合があります。

応答ヘッダーに必要な情報をできるだけ多く含める必要があると考える人もいますが、多くの場合、ヘッダーのみの空の応答になります。たとえば、作成時に201 Created、作成されたエンティティの ID を返して (リソース URI として) に配置しContent-Locationます。応答コンテンツは必要ありません。

個人的には、パブリック API を作成する場合は、コンテンツが多少冗長であっても、適切なヘッダーとコンテンツの両方を返すことをお勧めします。すなわち:

HTTP/1.1 404 Not found
Content-Type: application/json; charset=utf-8
...

{
   'Success': false,
   'Message': 'The user Mr. Gone wasn't found.'
}

(実際にはSuccessプロパティを含めませんが、API を設計するときの私の考え方によっては、含めたいと思うかもしれません)。

DEBUG モードで実行する場合、内部サービス呼び出しの文字列表現 ('Request': 'GetUser { id: 5 }'タイムスタンプやスタック トレースなど) も含めます。とはいえ、それはすべて都合の問題です。に基づいて、適切なユーザー フレンドリーなエラー メッセージを使用してクライアントをコーディングするのは簡単です404 Not found。ただし、その他のエラー (検証など) には、より多くのコンテキストが必要な場合があります。例えば:

HTTP/1.1 422 Validation Error
Content-Type: application/json; charset=utf-8
...

{
   'Success': false,
   'Message': 'The request had validation errors.',
   'Errors':
   {
       'UserName': 'The user name must be provided.',
       'Email': 'The email address is already in use.'
   }
}

ServiceStack.NET はデフォルトでこのようなことを行いますが、プロパティとコンテンツが若干異なります。Microsoft 独自の Web API フレームワークも同様のことを行います。関連する質問にリンクされている JSend 仕様は、別のバリエーションです。

等々。

要するに、いいえ、普遍的な慣習はありません - 少なくともまだです。多くの人 (私よりも多くのことを考えている) がそれに取り組んでいます。しかし、それでも、決してないかもしれません。そして、あなたの方法は完全に受け入れられます。

(はい、これは非常に長くなりました - ほとんどの場合、私はしばらくの間、同じ種類の「普遍的な慣習」を探し回っていたからです)。

ステータス コードの詳細については、これが優れた記事です (ここで引用するには長すぎます)。

于 2013-07-10T15:03:15.360 に答える
3

いいえ、これはいいかもしれませんが、単一の主要な標準はありません。successとを含める標準を自分で作成している場合に役立つ場合がありますがdetails、それは正確にどのように使用しているかによって異なります。大きな利点は、一貫性のために少なくとも独自のコード全体に標準を実装する場合だと思います。 -for-your-ajax-calls/

あなたのニーズに合っていれば、あなたの応答は完全に受け入れられます。successAPI を使用している場合、そのエラー応答は、応答コードと説明を含む「標準」として表示されますが、使いやすさのためにブール値が好きかもしれません。

于 2013-07-10T14:00:58.897 に答える
2

私の2セント:

何よりも、応答として送り返すステータスコードが最良のエラーインジケーターであり、4xx と 5xx の範囲で多くのオプションを提供します... (ティーポットからコーヒーを HttpGET しようとする場合でも、使用できます418:D)

200 以外のものは何らかのエラーであり、http ステータス コードは十分に文書化されており、その場合に使用する必要があるため、それ以上のエラー メッセージは実際には必要ありません (エラーの説明はステータス コードによって暗示されます)。リクエストを実行するのはブラウザであり、ブラウザはエラー メッセージを気にせず、ステータス コードだけを気にします。

余分なエラーメッセージは、ハッキングの試みに対してあまりにも多くの情報を遠ざける可能性もあります. つまり、403 Forbidden を返すだけで十分な情報であり、「許可されていません。代わりに「1234」をパスワードとして使用してください」というメッセージを返すべきではありません :)

于 2013-07-10T13:37:00.657 に答える
0

私は通常、サーバー側システムの名前、構造、および内容を実践の問題として採用しています。

このプラクティスにより、フロントエンド開発者は、バックエンド開発者が既に理解している語彙を使用して通信できるようになります。また、フロントエンド開発者やデザイナーが考案した新しいフォーマットの実装をバックエンド開発者に課すという標準/前例を設定することはありません。新しい概念 (エラーはエラーです。特定のエラーの単なる属性である「タイプ」と「メタ」について、髪を分けないようにしましょう。)

たとえば、エラーの詳細を「JSON クライアント」に返し、サービス エンドポイントが C# を使用して実装されている場合、次のような JSON ドキュメントを返す必要があります。

{ 
  "Message": "An error has occurred.", 
  "ExceptionMessage": "Index was outside the bounds of the array.", 
  "ExceptionType": "System.IndexOutOfRangeException", 
  "StackTrace": "   at WebApiTest.TestController.Post(Uri uri) in c:\\Temp\\WebApiTest\\WebApiTest\\TestController.cs:line 18\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClassf.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)\r\n   at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)",
}

もちろん、受け入れられた答えをオウムにするのではなく、特にあなたが多言語(または単に何らかの方法で確信がない「まったく新しいプログラマー」)である場合は、均一性の価値が非常に大きいことを伝えたいだけです。

今は問題にならないかもしれませんが、2 年、3 年、または 5 年のメンテナンスで気にし始めるかもしれません。また、同様の慣行を採用している他の開発者に出くわすと、長期的には「再トレーニング」する必要があることに気付くかもしれません。チームで新しいフォーマットを発明しようとしているのはあなただけです (それが必要でない場合)。

明確にするために、例外をクライアントにシリアル化することをお勧めしていません。ただし、これは、デバッグ、安全なプライベート クラウド、または機密データ/IP がない場合など、多くのシナリオで完全に有効なオプションである可能性があります。

于 2015-06-05T03:30:31.003 に答える