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