throw new HttpException((int)HttpStatusCode.BadRequest, "Bad Request.");
HttpException
在ASP.NET Core中不存在。它的等效代码是什么?
throw new HttpException((int)HttpStatusCode.BadRequest, "Bad Request.");
HttpException
在ASP.NET Core中不存在。它的等效代码是什么?
我实现了自己的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>();
}
}
Startup.Configure
之前预先注册它? - CallMeLaNN或者,如果您只想返回任意状态代码,并且不关心基于异常的方法,可以使用
return new HttpStatusCodeResult(400);
更新:截至.NET Core RC 2,已删除Http前缀。现在是:
return new StatusCodeResult(400);
new
关键字,我猜 (StatusCodeResult) Activator.CreateInstance(typeof(StatusCodeResult), 400);
可以满足需求。或者你可以创建一个 StatusCodeFactory 类来生成新的状态码。 - JeremyMicrosoft.AspNet.Mvc.Controller
是一个基类,提供了一个重载的HttpBadRequest(string)
方法,该方法接收一个错误消息并返回给客户端。因此,在控制器操作中可以调用以下代码:return HttpBadRequest("Bad Request.");
我的看法是,在控制器操作中调用的任何私有方法都应该完全具备 http 上下文感知能力并返回一个 IActionResult
,或者执行一些与其处于 http 管道内部无关的小任务。尽管这是我的个人意见,但是执行某些业务逻辑的类不应该返回 HTTP 状态码,而是应该抛出自己的异常,这些异常可以在控制器/操作级别进行捕获和转换。
HttpException
的旧 MVC 5 应用程序。如果可以选择性地提供相同的概念,则移植将变得更加容易。 - Muhammad Rehan Saeedreturn NotFound();
作为操作结果。 - Vasily Hallapp.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 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://learn.microsoft.com/en-us/aspnet/core/web-api/action-return-types?view=aspnetcore-3.1
Response.WriteAsync
来设置响应体。谢谢。 - StackOverflowerawait context.Response.WriteAsync(httpException.Message);`
- ToDevAndBeyond