ASP.NET MVC 5 では、HTTP コードでHttpExceptionをスローすることができ、これにより応答が次のように設定されます。
throw new HttpException((int)HttpStatusCode.BadRequest, "Bad Request.");
HttpException
ASP.NET Core には存在しません。同等のコードは何ですか?
ASP.NET MVC 5 では、HTTP コードでHttpExceptionをスローすることができ、これにより応答が次のように設定されます。
throw new HttpException((int)HttpStatusCode.BadRequest, "Bad Request.");
HttpException
ASP.NET Core には存在しません。同等のコードは何ですか?
@davidfowl との簡単なチャットの後、ASP.NET 5 にはそのような概念がないHttpException
かHttpResponseException
、「魔法のように」応答メッセージに変わるようです。
できることは、MiddleWare を介して ASP.NET 5 パイプラインにフックし、例外を処理するパイプラインを作成することです。
以下は、パイプラインのさらに上で例外が発生した場合に応答ステータス コードを 500 に設定するエラー ハンドラ ミドルウェアのソース コードの例です。
public class ErrorHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly ErrorHandlerOptions _options;
private readonly ILogger _logger;
public ErrorHandlerMiddleware(RequestDelegate next,
ILoggerFactory loggerFactory,
ErrorHandlerOptions options)
{
_next = next;
_options = options;
_logger = loggerFactory.CreateLogger<ErrorHandlerMiddleware>();
if (_options.ErrorHandler == null)
{
_options.ErrorHandler = _next;
}
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError("An unhandled exception has occurred: " + ex.Message, ex);
if (context.Response.HasStarted)
{
_logger.LogWarning("The response has already started,
the error handler will not be executed.");
throw;
}
PathString originalPath = context.Request.Path;
if (_options.ErrorHandlingPath.HasValue)
{
context.Request.Path = _options.ErrorHandlingPath;
}
try
{
var errorHandlerFeature = new ErrorHandlerFeature()
{
Error = ex,
};
context.SetFeature<IErrorHandlerFeature>(errorHandlerFeature);
context.Response.StatusCode = 500;
context.Response.Headers.Clear();
await _options.ErrorHandler(context);
return;
}
catch (Exception ex2)
{
_logger.LogError("An exception was thrown attempting
to execute the error handler.", ex2);
}
finally
{
context.Request.Path = originalPath;
}
throw; // Re-throw the original if we couldn't handle it
}
}
}
そして、あなたはそれを登録する必要がありますStartUp.cs
:
public class Startup
{
public void Configure(IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerfactory)
{
app.UseMiddleWare<ExceptionHandlerMiddleware>();
}
}
または、任意のステータス コードを返したいだけで、例外ベースのアプローチに関心がない場合は、次を使用できます。
return new HttpStatusCodeResult(400);
更新: .NET Core RC 2 以降、Http プレフィックスは削除されました。それは今です:
return new StatusCodeResult(400);
基本クラスは、クライアントに返すエラー メッセージを受け取るオーバーロードをMicrosoft.AspNet.Mvc.Controller
公開します。HttpBadRequest(string)
したがって、コントローラー アクション内から、次のように呼び出すことができます。
return HttpBadRequest("Bad Request.");
最終的には、コントローラ アクション内から呼び出されるプライベート メソッドは、完全に http コンテキストを認識して を返すIActionResult
か、http パイプライン内にあるという事実から完全に分離された他の小さなタスクを実行する必要があると、私の鼻は言います。これは私の個人的な意見ですが、ビジネス ロジックの一部を実行するクラスは、HTTP ステータス コードを返すのではなく、コントローラー/アクション レベルでキャッチして変換できる独自の例外をスローする必要があります。
これは@muhammad-rehan-saeedの回答の拡張版です。条件付きで例外をログに記録し、http キャッシュを無効にします。
これと UseDeveloperExceptionPage を使用する場合は、この前にUseDeveloperExceptionPage を呼び出す必要があります。
Startup.cs:
app.UseMiddleware<HttpExceptionMiddleware>();
HttpExceptionMiddleware.cs
/**
* Error handling: throw HTTPException(s) in business logic, generate correct response with correct httpStatusCode + short error messages.
* If the exception is a server error (status 5XX), this exception is logged.
*/
internal class HttpExceptionMiddleware
{
private readonly RequestDelegate next;
public HttpExceptionMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await this.next.Invoke(context);
}
catch (HttpException e)
{
var response = context.Response;
if (response.HasStarted)
{
throw;
}
int statusCode = (int) e.StatusCode;
if (statusCode >= 500 && statusCode <= 599)
{
logger.LogError(e, "Server exception");
}
response.Clear();
response.StatusCode = statusCode;
response.ContentType = "application/json; charset=utf-8";
response.Headers[HeaderNames.CacheControl] = "no-cache";
response.Headers[HeaderNames.Pragma] = "no-cache";
response.Headers[HeaderNames.Expires] = "-1";
response.Headers.Remove(HeaderNames.ETag);
var bodyObj = new {
Message = e.BaseMessage,
Status = e.StatusCode.ToString()
};
var body = JsonSerializer.Serialize(bodyObj);
await context.Response.WriteAsync(body);
}
}
}
HTTPException.cs
public class HttpException : Exception
{
public HttpStatusCode StatusCode { get; }
public HttpException(HttpStatusCode statusCode)
{
this.StatusCode = statusCode;
}
public HttpException(int httpStatusCode)
: this((HttpStatusCode) httpStatusCode)
{
}
public HttpException(HttpStatusCode statusCode, string message)
: base(message)
{
this.StatusCode = statusCode;
}
public HttpException(int httpStatusCode, string message)
: this((HttpStatusCode) httpStatusCode, message)
{
}
public HttpException(HttpStatusCode statusCode, string message, Exception inner)
: base(message, inner)
{
}
public HttpException(int httpStatusCode, string message, Exception inner)
: this((HttpStatusCode) httpStatusCode, message, inner)
{
}
}
よりもこのコードの方が良い結果が得られました:
ASP.NET Core Web API の例外処理もご覧ください。