From 7ad8f77835f691204c5b0d01e08cc17d815333bf Mon Sep 17 00:00:00 2001 From: Fumika Koyama <134590282+fkoyama@users.noreply.github.com> Date: Thu, 2 May 2024 13:36:01 +0900 Subject: [PATCH] =?UTF-8?q?ApiBehaviorOptions.SuppressMapClientErrors?= =?UTF-8?q?=E3=82=92=E6=9C=89=E5=8A=B9=E3=81=AB=E3=81=99=E3=82=8B(?= =?UTF-8?q?=E3=83=89=E3=82=AD=E3=83=A5=E3=83=A1=E3=83=B3=E3=83=88)=20(#118?= =?UTF-8?q?5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Azure AD B2C サンプルのReadMeの誤字修正とcspellの除外設定追加 (#1051) * cspellの除外設定を追加。 * 誤字修正。 --------- Co-authored-by: Fumika Koyama * アプリケーションアーキテクチャ概要編からコンソールアプリの要件別サンプルにリンクを張る (#1057) * リンクを追加 * 冗長な記載を修正 * documentsのreadmeを最新化する (#1062) * フォルダー構造を修正。 * 「テスト方針」と「画像ファイル」のフォルダー構成を修正。 --------- Co-authored-by: Fumika Koyama * ドキュメント追加。 * ProblemDetailsの指定が不要だったので戻す。 * 指摘事項に対応。 * 不要なusingを削除。 --------- Co-authored-by: Fumika Koyama Co-authored-by: kentah <158997636+KentaHizume@users.noreply.github.com> --- .../configure-asp-net-core-web-api-project.md | 43 ++++++++++++++ .../Controllers/UsersController.cs | 2 +- .../src/Dressca.Web/dressca-api.json | 38 +------------ .../api-client/.openapi-generator/FILES | 1 - .../src/generated/api-client/api/users-api.ts | 2 - .../src/generated/api-client/models/index.ts | 1 - .../api-client/models/problem-details.ts | 56 ------------------- 7 files changed, 45 insertions(+), 98 deletions(-) delete mode 100644 samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/models/problem-details.ts diff --git a/documents/contents/guidebooks/how-to-develop/dotnet/configure-asp-net-core-web-api-project.md b/documents/contents/guidebooks/how-to-develop/dotnet/configure-asp-net-core-web-api-project.md index 191065961..b39206bab 100644 --- a/documents/contents/guidebooks/how-to-develop/dotnet/configure-asp-net-core-web-api-project.md +++ b/documents/contents/guidebooks/how-to-develop/dotnet/configure-asp-net-core-web-api-project.md @@ -216,6 +216,49 @@ Open API 仕様書のファイルがビルド時に生成されるようプロ } ``` +### Web API コントローラーのエラーレスポンス形式の指定 {#set-error-response-type} + +Web API コントローラーが返却するエラーレスポンスの形式は `ProducesResponseType` 属性の `Type` パラメーターで明示的に指定します。 +`Type` パラメーターに `typeof(ProblemDetails)` を指定することで、[RFC 9457](https://datatracker.ietf.org/doc/html/rfc9457) ([日本語訳付き](https://tex2e.github.io/rfc-translater/html/rfc9457.html)) に従ったエラーレスポンスを返却します。 + +また、実際のレスポンス形式と Open API 定義書に記載のレスポンス形式の不一致を防ぐため、 `Program.cs` で `ApiBehaviorOptions.SuppressMapClientErrors` を `true` に設定します。 +`SuppressMapClientErrors` の既定値は `false` であり、この場合エラーレスポンスの型を指定しない限りエラーは自動的に `ProblemDetails` にマッピングされ、 Open API 定義書にも反映されます。 +しかし、この設定が有効になるのは Web API コントローラーの範囲であり、たとえば `Program.cs` でインジェクションした外部サービスの機能が自動的にエラーを返却する場合等は `ProblemDetails` の形式になりません。つまり、 Open API 定義書と実際に返されるエラーレスポンスの形式に差異ができてしまいます。これを防ぐため、 `ApiBehaviorOptions.SuppressMapClientErrors` を `true` に設定し、 `ProblemDetails` への自動的なマッピングを停止します。 + +??? example "エラーレスポンス形式の設定例" + `ApiBehaviorOptions.SuppressMapClientErrors` を `true` に設定します。 + + ```csharp title="Program.cs" + builder.Services + .AddControllers() + .ConfigureApiBehaviorOptions(options => + { + options.SuppressMapClientErrors = true; + }); + ``` + + `ProducesResponseType` 属性の `Type` に `typeof(ProblemDetails)` を指定します。 + + ```csharp title="SampleController.cs" + using Microsoft.AspNetCore.Mvc; + + namespace AaaSubSystem.Web.Controllers; + + [Route("api/sample")] + [ApiController] + [Produces("application/json")] + public class SampleController : ControllerBase + { + [HttpGet] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserResponse))] + [ProducesResponseType(StatusCodes.Status500InternalServerError, Type = typeof(ProblemDetails))] + public IActionResult GetSample() + { + // 省略 + } + } + ``` + ## HTTP 400 時のログ出力 {#logging-on-http-400} Web API から HTTP 400 のレスポンスを返却する際、問題の原因となった入力値の情報をログに記録しましょう。 diff --git a/samples/AzureADB2CAuth/auth-backend/src/Dressca.Web/Controllers/UsersController.cs b/samples/AzureADB2CAuth/auth-backend/src/Dressca.Web/Controllers/UsersController.cs index f05d8b1e8..b762f4859 100644 --- a/samples/AzureADB2CAuth/auth-backend/src/Dressca.Web/Controllers/UsersController.cs +++ b/samples/AzureADB2CAuth/auth-backend/src/Dressca.Web/Controllers/UsersController.cs @@ -22,7 +22,7 @@ public class UsersController : ControllerBase /// 認証されていない。 [HttpGet] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(UserResponse))] - [ProducesResponseType(StatusCodes.Status401Unauthorized, Type = typeof(ProblemDetails))] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] [Authorize] [OpenApiOperation("getUser")] public IActionResult GetUser() diff --git a/samples/AzureADB2CAuth/auth-backend/src/Dressca.Web/dressca-api.json b/samples/AzureADB2CAuth/auth-backend/src/Dressca.Web/dressca-api.json index 6314f44ae..e376c67b7 100644 --- a/samples/AzureADB2CAuth/auth-backend/src/Dressca.Web/dressca-api.json +++ b/samples/AzureADB2CAuth/auth-backend/src/Dressca.Web/dressca-api.json @@ -53,14 +53,7 @@ } }, "401": { - "description": "認証されていない。", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ProblemDetails" - } - } - } + "description": "認証されていない。" } }, "security": [ @@ -102,35 +95,6 @@ "minLength": 1 } } - }, - "ProblemDetails": { - "type": "object", - "additionalProperties": { - "nullable": true - }, - "properties": { - "type": { - "type": "string", - "nullable": true - }, - "title": { - "type": "string", - "nullable": true - }, - "status": { - "type": "integer", - "format": "int32", - "nullable": true - }, - "detail": { - "type": "string", - "nullable": true - }, - "instance": { - "type": "string", - "nullable": true - } - } } }, "securitySchemes": { diff --git a/samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/.openapi-generator/FILES b/samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/.openapi-generator/FILES index 3c83e66f3..108ad79bf 100644 --- a/samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/.openapi-generator/FILES +++ b/samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/.openapi-generator/FILES @@ -10,6 +10,5 @@ configuration.ts git_push.sh index.ts models/index.ts -models/problem-details.ts models/server-time-response.ts models/user-response.ts diff --git a/samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/api/users-api.ts b/samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/api/users-api.ts index 2fa82645d..6bd237b62 100644 --- a/samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/api/users-api.ts +++ b/samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/api/users-api.ts @@ -21,8 +21,6 @@ import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObj // @ts-ignore import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base'; // @ts-ignore -import { ProblemDetails } from '../models'; -// @ts-ignore import { UserResponse } from '../models'; /** * UsersApi - axios parameter creator diff --git a/samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/models/index.ts b/samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/models/index.ts index 702e1c0e3..c15bf635a 100644 --- a/samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/models/index.ts +++ b/samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/models/index.ts @@ -1,3 +1,2 @@ -export * from './problem-details'; export * from './server-time-response'; export * from './user-response'; diff --git a/samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/models/problem-details.ts b/samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/models/problem-details.ts deleted file mode 100644 index 0315c259b..000000000 --- a/samples/AzureADB2CAuth/auth-frontend/src/generated/api-client/models/problem-details.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/** - * Azure AD B2C ユーザー認証 - * Azure AD B2Cを利用したユーザー認証機能を提供するサンプルアプリケーションです。 - * - * The version of the OpenAPI document: 1.0.0 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - - -/** - * - * @export - * @interface ProblemDetails - */ -export interface ProblemDetails { - [key: string]: any | any; - - /** - * - * @type {string} - * @memberof ProblemDetails - */ - 'type'?: string | null; - /** - * - * @type {string} - * @memberof ProblemDetails - */ - 'title'?: string | null; - /** - * - * @type {number} - * @memberof ProblemDetails - */ - 'status'?: number | null; - /** - * - * @type {string} - * @memberof ProblemDetails - */ - 'detail'?: string | null; - /** - * - * @type {string} - * @memberof ProblemDetails - */ - 'instance'?: string | null; -} -