[英].Net Core: Return IActionResult from a custom Exception Middleware
I have created a new Exception middleware in my .Net Core application.我在我的 .Net Core 应用程序中创建了一个新的 Exception 中间件。 All the exceptions throughout the application are captured and logged here.
整个应用程序中的所有异常都在此处捕获并记录。 What I want is to return a IActionResult type like InternalServerError() or NotFound() from the Exception Middleware and not do response.WriteAsync as below.
我想要的是从异常中间件返回一个 IActionResult 类型,如 InternalServerError() 或 NotFound() ,而不是像下面那样做 response.WriteAsync 。
Controller Method:控制器方法:
public async Task<IActionResult> Post()
{
//Do Something
return Ok();
}
Middleware:中间件:
public class ExceptionMiddleware
{
private readonly RequestDelegate _next;
public ExceptionMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next.Invoke(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex);
}
}
private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
var response = context.Response;
var statusCode = (int)HttpStatusCode.InternalServerError;
var message = exception.Message;
var description = exception.Message;
response.ContentType = "application/json";
response.StatusCode = statusCode;
await response.WriteAsync(JsonConvert.SerializeObject(new ErrorResponse
{
Message = message,
Description = description
}));
}
}
IActionResult
is a thing from MVC, so it is only available within the MVC pipeline (including Razor Pages). IActionResult
是来自 MVC 的东西,所以它只在 MVC 管道中可用(包括 Razor Pages)。 Just before the MVC middleware terminates, it will execute those action results using ExecuteAsync
.就在 MVC 中间件终止之前,它将使用
ExecuteAsync
执行这些操作结果。 That method is then responsible of writing that response to HttpContext.Response
.然后该方法负责将该响应写入
HttpContext.Response
。
So in custom middleware, you cannot just set an action result and have it executed, since you are not running within the MVC pipeline.因此,在自定义中间件中,您不能只设置操作结果并执行它,因为您不在 MVC 管道中运行。 However, with that knowledge, you can simply execute the result yourself.
但是,有了这些知识,您可以自己简单地执行结果。
Let's say you want to execute a NotFoundResult
which is what Controller.NotFound()
creates.假设您要执行一个
NotFoundResult
,它是Controller.NotFound()
创建的。 So you create that result and call ExecuteAsync
with an .所以,你创建的结果,并呼吁
ExecuteAsync
用。 That executor will be able to execute that result object and write to the response:该执行器将能够执行该结果对象并写入响应:
var result = new NotFoundResult();
await result.ExecuteAsync(new ActionContext
{
HttpContext = context,
});
That's not really possible due to where IActionResult
and middleware sit in relation to one another in the architecture.由于
IActionResult
和中间件在体系结构中彼此相关,因此这实际上是不可能的。 Middleware sits much lower, and so it can't reach further up the stack to IActionResult
.中间件的位置要低得多,因此它无法进一步向上到达
IActionResult
堆栈。 Here's an answer that talks more about it: https://stackoverflow.com/a/43111292/12431728这是一个更详细地讨论它的答案: https : //stackoverflow.com/a/43111292/12431728
What you're trying to do can be done by simply adding this line:只需添加以下行即可完成您要执行的操作:
app.UseStatusCodePagesWithReExecute("/Public/Error", "?statusCode={0}");
to the Configure method in the Startup.cs.到 Startup.cs 中的 Configure 方法。 Then you can create your Public Controller with Error method that does the following:
然后,您可以使用执行以下操作的 Error 方法创建公共控制器:
[AllowAnonymous]
public IActionResult Error(int? statusCode = null)
{
// Retrieve error information in case of internal errors.
var error = HttpContext.Features.Get<IExceptionHandlerFeature>()?.Error;
var path = HttpContext.Features.Get<IExceptionHandlerPathFeature>()?.Path;
// TODO: Redirect here based on your status code or perhaps just render different views for different status codes.
}
There is also another middleware that allows you to do a similar thing:还有另一个中间件可以让你做类似的事情:
app.UseStatusCodePages(async context =>
{
if (context.HttpContext.Response.StatusCode == 401)
{
context.HttpContext.Response.Redirect("Errors/Unauthorized/");
}
else if (context.HttpContext.Response.StatusCode == 500)
{
// TODO: Redirect for 500 and so on...
}
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.