C# ASP.NET核心相当于ASP.NET MVC 5';https异常
在ASP.NET MVC 5中,您可以抛出一个带有HTTP代码的,这将设置如下响应:C# ASP.NET核心相当于ASP.NET MVC 5';https异常,c#,.net,asp.net-core,asp.net-core-mvc,httpexception,C#,.net,Asp.net Core,Asp.net Core Mvc,Httpexception,在ASP.NET MVC 5中,您可以抛出一个带有HTTP代码的,这将设置如下响应: throw new HttpException((int)HttpStatusCode.BadRequest, "Bad Request."); HttpException在ASP.NET核心中不存在。什么是等效代码?在a之后,ASP.NET 5似乎没有“神奇地”变成响应消息的HttpException或HttpResponseException的概念 您可以做的是,创建一个为您处理异常的程序 下面是他们的错
throw new HttpException((int)HttpStatusCode.BadRequest, "Bad Request.");
HttpException
在ASP.NET核心中不存在。什么是等效代码?在a之后,ASP.NET 5似乎没有“神奇地”变成响应消息的HttpException
或HttpResponseException
的概念
您可以做的是,创建一个为您处理异常的程序
下面是他们的错误处理程序中间件的示例,该中间件将在管道上出现异常时将响应状态代码设置为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
}
}
}
或者,如果您只想返回任意状态代码,而不关心基于异常的方法,则可以使用
return new HttpStatusCodeResult(400);
更新:从.NET Core RC 2开始,Http前缀被删除。现在是:
return new StatusCodeResult(400);
我实现了自己的
HttpException
和支持中间件,它捕获所有HttpException
,并将它们转换为相应的错误响应。下面是简短的摘录。您还可以使用Nuget包
Startup.cs中的使用示例
扩展方法
从长远来看,我建议不要使用异常来返回错误。异常比仅从方法返回错误要慢。Microsoft.AspNet.Mvc.Controller基类公开了一个
HttpBadRequest(string)
重载,该重载会将错误消息返回到客户端。因此,在控制器操作中,您可以调用:
return HttpBadRequest("Bad Request.");
最终,我的鼻子说,从控制器操作中调用的任何私有方法都应该是完全http上下文感知的,并返回一个
IActionResult
,或者执行一些与http管道内部的事实完全隔离的其他小任务。虽然这是我个人的观点,但执行某些业务逻辑的类不应该返回HTTP状态码,而应该抛出自己的异常,这些异常可以在控制器/操作级别捕获和转换。ASP.NET核心本身没有等价物。正如其他人所说,实现这一点的方法是使用中间件和您自己的异常
NuGet包正是这样做的
用于通过HTTP返回异常的中间件和扩展,如ASP.NET核心问题详细信息。问题详细信息是一种机器可读的格式,用于根据指定HTTP API响应中的错误。但您不仅限于将异常结果作为问题详细信息返回,还可以为自己的自定义格式创建自己的映射器
它是可配置的,并且有很好的文档记录
以下是开箱即用的例外情况列表:
4xx
- 400 BadRequestException
- 400 InvalidModelException
- 400 ValidationErrorException
- 400无效文件例外
- 401未经授权的例外情况
- 403禁止例外
- 404 NotFoundException
- 404 NotFoundException
- 409冲突例外
- 409保护异常
- 415不支持的MediaTypeException
- 500 InternalServerErrorException
- 500 DbErrorException
- 500序列化错误异常
- 503 ServiceUnavailableException
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);
}
[HttpGet(“{id}”)]
[产品响应类型(StatusCodes.Status200OK)]
[产品响应类型(StatusCodes.Status404NotFound)]
公共操作结果GetByItemId(int id)
{
...
如果(结果==null)
{
返回NotFound();
}
返回Ok(结果);
}
更多详情请参见:这里是@muhammad rehan saeed answer的扩展版本。 它有条件地记录异常并禁用http缓存。
如果使用此选项并使用developerCeptionPage,则应在此之前调用UsedeveloperCeptionPage Startup.cs:
app.UseMiddleware();
HttpExceptionMiddleware.cs
/**
*错误处理:在业务逻辑中抛出HTTPException,使用正确的httpStatusCode+短错误消息生成正确的响应。
*如果异常是服务器错误(状态5XX),则会记录此异常。
*/
内部类HttpExceptionMiddleware
{
私有只读请求委托下一步;
公共HttpExceptionMiddleware(RequestDelegate下一步)
{
this.next=next;
}
公共异步任务调用(HttpContext上下文)
{
尝试
{
等待这个。下一步。调用(上下文);
}
catch(httpe异常)
{
var-response=context.response;
if(response.HasStarted)
{
投掷;
}
int statusCode=(int)e.statusCode;
如果(statusCode>=500&&statusCode@Rehan这是我们必须编写的。他们不打算将该功能引入MVC 6。每个连接都将通过中间件管道完成。@Rehanseed我同意,这是非常有用的功能,我也经常使用它。ASP.NET 5是开源的,我们可以自己应用该功能如果我们愿意,我将添加您的代码并默认启用它。谢谢您的帮助。@davidfoll哪种扩展方法?@YuvalItzchakov我使用空的ASP.NET 5 Web API并实现nice 500错误页面可能来自此诊断中间件。如何替换此中间件或在生产中关闭?框架是否在测试之前预先注册它启动。配置被调用的
?是的,直接在操作中调用肯定是最好的方法。但有时,操作调用执行特定工作的私有方法(返回ActionResult以外的内容),有时您希望此方法可以抛出异常以生成响应(主要是错误,比如400个错误请求,403个禁止)。在这种情况下,例外是一个不错的选择
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; } }
}
return HttpBadRequest("Bad Request.");
[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<ITEMS_TYPE> GetByItemId(int id)
{
...
if (result == null)
{
return NotFound();
}
return Ok(result);
}