web-dev-qa-db-ja.com

ASP.Net Coreモデルバインディングエラーをカスタマイズするにはどうすればよいですか?

Web API(Asp.net Core 2.1)から標準化されたエラー応答のみを返したいのですが、モデルバインディングエラーを処理する方法がわかりません。

プロジェクトは、「ASP.NET Core Web Application」>「API」テンプレートから作成されたばかりです。私は次のように定義されたシンプルなアクションを持っています:

[Route("[controller]")]
[ApiController]
public class MyTestController : ControllerBase
{
    [HttpGet("{id}")]
    public ActionResult<TestModel> Get(Guid id)
    {
        return new TestModel() { Greeting = "Hello World!" };
    }
}

public class TestModel
{
    public string Greeting { get; set; }
}

無効なGUID(たとえば、https://localhost:44303/MyTest/asdf)を使用してこのアクションにリクエストを行うと、次の応答が返されます。

{
    "id": [
        "The value 'asdf' is not valid."
    ]
}

Startup.Configureに次のコードがあります:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    JsonErrorMiddleware.CreateSingleton(env);

    if (!env.IsDevelopment())
    {
        app.UseHsts();
    }

    app
        .UseHttpsRedirection()
        .UseStatusCodePages(async ctx => { await JsonErrorMiddleware.Instance.Invoke(ctx.HttpContext); })
        .UseExceptionHandler(new ExceptionHandlerOptions() { ExceptionHandler = JsonErrorMiddleware.Instance.Invoke })
        .UseMvc()
}

JsonErrorMiddlewareは、エラーを正しい形状に変換して返すようにし、それらを応答に入れるクラスです。モデルバインディングエラーではまったく呼び出されません(Exceptionはスローされず、UseStatusCodePagesは呼び出されません)。

モデルバインディングにフックして、プロジェクトのすべてのアクションで標準化されたエラー応答を提供するにはどうすればよいですか?

たくさんの記事を読みましたが、それらはすべて、グローバルな例外処理または検証エラーについて議論しているようです。

13
Brian

ASP.NET Core 2.1が_[ApiController]_属性を追加したことは注目に値します。この属性は、特に、渡されたBadRequestObjectResultModelStateを返すことでモデル検証エラーを自動的に処理します。 、コントローラーをその属性で装飾する場合、if (!ModelState.IsValid)チェックを行う必要はなくなりました。

さらに、機能も拡張可能です。 Startupでは、次を追加できます。

_services.Configure<ApiBehaviorOptions>(o =>
{
    o.InvalidModelStateResponseFactory = actionContext =>
        new BadRequestObjectResult(actionContext.ModelState);
});
_

上記はすでにデフォルトで行われていることですが、InvalidModelStateResponseFactoryが設定されているラムダをカスタマイズして、好きなものを返すことができます。

29
Chris Pratt