C# ASP.NET核心MVC(2.2)错误中间件未触发错误页

C# ASP.NET核心MVC(2.2)错误中间件未触发错误页,c#,asp.net,asp.net-core,asp.net-core-mvc,C#,Asp.net,Asp.net Core,Asp.net Core Mvc,在我的ASP.NET核心MVC2.2应用程序中,我已经完成了全局错误处理类的设置。我通过在app.UseMvc之前使用app.usembiddleware将这个类注入到我的项目的Startup.cs中。但是,当我将Response.StatusCode设置为相应的代码400、404、500并返回错误页面控制器没有调用的响应时,每个异常都会触发此错误处理程序。但是,如果我手动返回错误请求;从我的控制器调用错误页控制器 甚至可以从错误处理程序中间件类触发错误页面吗?如果是这样的话,我如何才能做到这样

在我的ASP.NET核心MVC2.2应用程序中,我已经完成了全局错误处理类的设置。我通过在app.UseMvc之前使用app.usembiddleware将这个类注入到我的项目的Startup.cs中。但是,当我将Response.StatusCode设置为相应的代码400、404、500并返回错误页面控制器没有调用的响应时,每个异常都会触发此错误处理程序。但是,如果我手动返回错误请求;从我的控制器调用错误页控制器

甚至可以从错误处理程序中间件类触发错误页面吗?如果是这样的话,我如何才能做到这样的行为

下面是我处理中间件类的错误

public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate nextDelegate;

    public ErrorHandlingMiddleware(RequestDelegate nextDelegate)
    {
        this.nextDelegate = nextDelegate;
    }

    public async Task Invoke(HttpContext context, IOptions<MvcJsonOptions> options)
    {
        try
        {
            await this.nextDelegate(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex, options);
        }
    }

    private static Task HandleExceptionAsync(HttpContext context, Exception ex, IOptions<MvcJsonOptions> options)
    {
        var httpStatusCode = HttpStatusCode.InternalServerError;

        if (ex is CommonApiException commonApiException)
        {
            httpStatusCode = (HttpStatusCode)commonApiException.StatusCode;
        }

        var result = JsonConvert.SerializeObject(new { error = ex.Message }, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() });
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)httpStatusCode;

        return context.Response.WriteAsync(result);
    }
}
甚至可以从错误处理程序中间件类触发错误页面吗?如果是这样的话,我如何才能做到这样的行为

是。请尝试修改您的HandleExceptionAsync ErrorHandlingMiddleware以重写您的url:

public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate nextDelegate;

    public ErrorHandlingMiddleware(RequestDelegate nextDelegate)
    {
        this.nextDelegate = nextDelegate;
    }

    public async Task Invoke(HttpContext context, IOptions<MvcJsonOptions> options)
    {
        try
        {
            await this.nextDelegate(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex, options);
        }
    }

    private async Task HandleExceptionAsync(HttpContext context, Exception ex, IOptions<MvcJsonOptions> options)
    {
        var httpStatusCode = HttpStatusCode.InternalServerError;

        PathString originalPath = context.Request.Path;
        context.Request.Path = "/Error/StatusCode" + (int)httpStatusCode;
        try
        {
            var exceptionHandlerFeature = new ExceptionHandlerFeature()
            {
                Error = ex,
                Path = originalPath.Value,
            };
            context.Features.Set<IExceptionHandlerFeature>(exceptionHandlerFeature);
            context.Features.Set<IExceptionHandlerPathFeature>(exceptionHandlerFeature);
            context.Response.StatusCode = (int)httpStatusCode;

            await this.nextDelegate(context);
            return;
        }
        catch (Exception ex2)
        {
        }
        finally
        {
            context.Request.Path = originalPath;
        }
    }
}

你为什么有最后一个街区?将请求路径设置为原始路径的目的是什么?@Adrian Cruz它将在try块中返回,当您出现错误时使用finally块,它不会更改当前请求路径。如何编写它取决于您。谢谢。您的解决方案非常有效!我将把这作为答案。
public class ErrorController : Controller
{       
    [AllowAnonymous]
    [Route("Error")]
    [Route("Error/Index")]
    [Route("Error/500")]
    [SkipFilters("Bypass claims.")]
    public IActionResult Index()
    {
        return this.View();
    }

    [AllowAnonymous]
    [SkipFilters("Bypass claims.")]
    [Route("Error/StatusCode/{code}")]
    public IActionResult ErrorStatusCode(int code)
    {
        var statusCodeModel = new StatusCodeModel
        {
            ErrorStatusCode = code.ToString(),
            OperationId = Activity.Current.RootId
        };

        var statusCodeReExecuteFeature = this.HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
        if (statusCodeReExecuteFeature != null)
        {
            statusCodeModel.OriginalUrl =
                statusCodeReExecuteFeature.OriginalPathBase
                + statusCodeReExecuteFeature.OriginalPath
                + statusCodeReExecuteFeature.OriginalQueryString;
        }

        return this.View("StatusCode", statusCodeModel);
    }
}
 public class DummyController : Controller
    {

    [Route("Dummy")]
    public IActionResult Dummy()
    {
        throw new CommonApiException("Test Error");

        //return this.BadRequest(); //This triggers the error page controller.
    }
 }
public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate nextDelegate;

    public ErrorHandlingMiddleware(RequestDelegate nextDelegate)
    {
        this.nextDelegate = nextDelegate;
    }

    public async Task Invoke(HttpContext context, IOptions<MvcJsonOptions> options)
    {
        try
        {
            await this.nextDelegate(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex, options);
        }
    }

    private async Task HandleExceptionAsync(HttpContext context, Exception ex, IOptions<MvcJsonOptions> options)
    {
        var httpStatusCode = HttpStatusCode.InternalServerError;

        PathString originalPath = context.Request.Path;
        context.Request.Path = "/Error/StatusCode" + (int)httpStatusCode;
        try
        {
            var exceptionHandlerFeature = new ExceptionHandlerFeature()
            {
                Error = ex,
                Path = originalPath.Value,
            };
            context.Features.Set<IExceptionHandlerFeature>(exceptionHandlerFeature);
            context.Features.Set<IExceptionHandlerPathFeature>(exceptionHandlerFeature);
            context.Response.StatusCode = (int)httpStatusCode;

            await this.nextDelegate(context);
            return;
        }
        catch (Exception ex2)
        {
        }
        finally
        {
            context.Request.Path = originalPath;
        }
    }
}