web-dev-qa-db-ja.com

オブジェクトを返すASP.NET Core WebAPIコントローラーで例外をスローするにはどうすればよいですか?

Framework WebAPI 2には、次のようなコントローラーがあります。

[Route("create-license/{licenseKey}")]
public async Task<LicenseDetails> CreateLicenseAsync(string licenseKey, CreateLicenseRequest license)
{
    try
    {
        // ... controller-y stuff
        return await _service.DoSomethingAsync(license).ConfigureAwait(false);
    }
    catch (Exception e)
    {
        _logger.Error(e);
        const string msg = "Unable to PUT license creation request";
        throw new HttpResponseException(HttpStatusCode.InternalServerError, msg);
    }
}

案の定、メッセージとともに500エラーが返されます。

ASP.NET Core Web APIで同様のことを行うにはどうすればよいですか?

HttpRequestExceptionは存在しないようです。 HttpRequestMessageの代わりにオブジェクトを返し続けたいと思います。

11
rianjs

このようなものはどうですか。特定の例外メッセージを公開するミドルウェアを作成します。

public class ExceptionMiddleware
{
    private readonly RequestDelegate _next;

    public ExceptionMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            context.Response.ContentType = "text/plain";
            context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

            if (ex is ApplicationException)
            {
                await context.Response.WriteAsync(ex.Message);
            }
        }
    }
}

アプリで使用してください:

app.UseMiddleware<ExceptionMiddleware>();
app.UseMvc();

そして、アクションで例外をスローします:

[Route("create-license/{licenseKey}")]
public async Task<LicenseDetails> CreateLicenseAsync(string licenseKey, CreateLicenseRequest license)
{
    try
    {
        // ... controller-y stuff
        return await _service.DoSomethingAsync(license).ConfigureAwait(false);
    }
    catch (Exception e)
    {
        _logger.Error(e);
        const string msg = "Unable to PUT license creation request";
        throw new ApplicationException(msg);
    }
}

より良い方法は、IActionResultを返すことです。そうすれば、例外をスローする必要はありません。このような:

[Route("create-license/{licenseKey}")]
public async Task<IActionResult> CreateLicenseAsync(string licenseKey, CreateLicenseRequest license)
{
    try
    {
        // ... controller-y stuff
        return Ok(await _service.DoSomethingAsync(license).ConfigureAwait(false));
    }
    catch (Exception e)
    {
        _logger.Error(e);
        const string msg = "Unable to PUT license creation request";
        return StatusCode((int)HttpStatusCode.InternalServerError, msg)
    }
}
14
peco

すべてのアクションですべての例外をキャッチしない方が良いです。 ミドルウェア で残りのすべてをキャッチして(そしてHttpResponseにラップする)必要な例外をキャッチするだけです。

5
Zharro