![](/img/trans.png)
[英]ASP.NET Core equivalent for ASP.NET MVC BeginExecuteCore
[英]ASP.NET Core equivalent of ASP.NET MVC 5's HttpException
在 ASP.NET MVC 5 中,您可以使用 HTTP 代碼拋出HttpException ,這將設置響應如下:
throw new HttpException((int)HttpStatusCode.BadRequest, "Bad Request.");
ASP.NET Core 中不存在HttpException
。 什么是等效代碼?
我實現了我自己的HttpException
和支持中間件,它捕獲所有HttpException
並將它們轉換為相應的錯誤響應。 下面可以看到一個簡短的摘錄。 您還可以使用Boxed.AspNetCore Nuget 包。
public void Configure(IApplicationBuilder application)
{
application.UseIISPlatformHandler();
application.UseStatusCodePagesWithReExecute("/error/{0}");
application.UseHttpException();
application.UseMvc();
}
public static class ApplicationBuilderExtensions
{
public static IApplicationBuilder UseHttpException(this IApplicationBuilder application)
{
return application.UseMiddleware<HttpExceptionMiddleware>();
}
}
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 httpException)
{
context.Response.StatusCode = httpException.StatusCode;
var responseFeature = context.Features.Get<IHttpResponseFeature>();
responseFeature.ReasonPhrase = httpException.Message;
}
}
}
public class HttpException : Exception
{
private readonly int httpStatusCode;
public HttpException(int httpStatusCode)
{
this.httpStatusCode = httpStatusCode;
}
public HttpException(HttpStatusCode httpStatusCode)
{
this.httpStatusCode = (int)httpStatusCode;
}
public HttpException(int httpStatusCode, string message) : base(message)
{
this.httpStatusCode = httpStatusCode;
}
public HttpException(HttpStatusCode httpStatusCode, string message) : base(message)
{
this.httpStatusCode = (int)httpStatusCode;
}
public HttpException(int httpStatusCode, string message, Exception inner) : base(message, inner)
{
this.httpStatusCode = httpStatusCode;
}
public HttpException(HttpStatusCode httpStatusCode, string message, Exception inner) : base(message, inner)
{
this.httpStatusCode = (int)httpStatusCode;
}
public int StatusCode { get { return this.httpStatusCode; } }
}
從長遠來看,我建議不要使用異常來返回錯誤。 異常比僅僅從方法返回錯誤要慢。
在與 @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 狀態代碼,而應該拋出自己的異常,這些異常可以在控制器/操作級別捕獲和轉換。
ASP.NET Core 本身沒有等價物。 正如其他人所說,實現這一點的方法是使用中間件和您自己的例外。
Opw.HttpExceptions.AspNetCore NuGet 包正是這樣做的。
用於通過 HTTP 返回異常的中間件和擴展,例如作為 ASP.NET Core 問題詳細信息。 問題詳細信息是一種機器可讀格式,用於指定基於https://tools.ietf.org/html/rfc7807 的HTTP API 響應中的錯誤。 但您不僅限於將異常結果作為問題詳細信息返回,還可以為自己的自定義格式創建自己的映射器。
它是可配置的並且有據可查。
以下是現成可用的異常列表:
4xx從 ASP.NET Core 3 開始,您可以使用ActionResult
返回 HTTP 狀態代碼:
[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<ITEMS_TYPE> GetByItemId(int id)
{
...
if (result == null)
{
return NotFound();
}
return Ok(result);
}
更多細節在這里: https : //docs.microsoft.com/en-us/aspnet/core/web-api/action-return-types?view=aspnetcore-3.1
這是@muhammad-rehan-saeed 答案的擴展版本。 它有條件地記錄異常並禁用 http 緩存。
如果你使用這個和 UseDeveloperExceptionPage,你應該在這之前調用 UseDeveloperExceptionPage。
啟動.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)
{
}
}
我使用此代碼獲得了比使用更好的結果:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.