我认为这种变化是由于.NET Core - 在ASP.NET尝试一步到位,而ASP.NET Core只做您明确告诉它要做的事情(这就是为什么它更快、更便携的重要原因之一)。
如果您想在Core中获得此行为,则需要添加它,可以使用其他人编写的包或自己编写。
这很简单。首先,您需要一个自定义异常来检查:
public class StatusCodeException : Exception
{
public StatusCodeException(HttpStatusCode statusCode)
{
StatusCode = statusCode;
}
public HttpStatusCode StatusCode { get; set; }
}
然后您需要一个RequestDelegate
处理程序来检查新异常并将其转换为HTTP响应状态码:
public class StatusCodeExceptionHandler
{
private readonly RequestDelegate request;
public StatusCodeExceptionHandler(RequestDelegate next)
{
this.request = next;
}
public Task Invoke(HttpContext context) => this.InvokeAsync(context);
async Task InvokeAsync(HttpContext context)
{
try
{
await this.request(context);
}
catch (StatusCodeException exception)
{
context.Response.StatusCode = (int)exception.StatusCode;
context.Response.Headers.Clear();
}
}
}
然后在启动时将此中间件注册:
public class Startup
{
...
public void Configure(IApplicationBuilder app)
{
...
app.UseMiddleware<StatusCodeExceptionHandler>();
最后你可以在你的操作中抛出HTTP状态码异常,同时返回一个显式类型,这样你就可以轻松地进行单元测试:
public Thing Get(int id) {
Thing thing = GetThingFromDB();
if (thing == null)
throw new StatusCodeException(HttpStatusCode.NotFound);
return thing;
}
这很简单,可能有人写了一个更完整的版本,但我找不到或得到一个清晰的答案,解释为什么这个被删除了。
IActionResult
(HttpUnauthorizedResult
),因为这样可以将控制器的关注点保持在控制器内部,而不是从域深处抛出异常。你是否希望在抛出异常后仍然让请求被其他中间件处理?此外,这个异常是从每个控制器中抛出的吗? - Dr Rob Lang