简体   繁体   English

.Net Core:从自定义异常中间件返回 IActionResult

[英].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.

相关问题 从ASP.NET Core中的WebSocket请求返回什么IActionResult? - What IActionResult to return from a WebSocket request in ASP.NET Core? 在 .NET Core 中将 HttpResponseMessage 转换为 IActionResult - Convert from HttpResponseMessage to IActionResult in .NET Core 如何在ASP.NET Core中返回自定义HTTP状态/消息而不返回对象,IActionResult等? - How to return a custom HTTP status/message in ASP.NET Core without returning object, IActionResult, etc? 如何在 ASP.NET Core 中返回 403 Forbidden 响应作为 IActionResult - How to return 403 Forbidden response as IActionResult in ASP.NET Core .NET 核心 WebApi 从中间件向用户返回未经授权的代码 - .NET Core WebApi return Unathorized code to user from middleware 序列化前来自自定义中间件的 .Net Core 访问响应 - .Net Core Access Response From Custom Middleware Before Serialization 从 URL 返回文件作为 IActionResult - Return File from URL as IActionResult Net Core - 为什么异常中间件如此之慢? - Net Core - Why exception middleware is so slow? ASP.Net Core 异常处理中间件 - ASP.Net Core exception handling middleware ASP.NET 核心任务<iactionresult>没有异步就无法返回 NotFound() 和 OK()</iactionresult> - ASP.NET Core Task<IActionResult> cannot return NotFound() and OK() without async
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM