'ASP.NET Core MVC (2.2) Error Middle-ware not triggering error pages
In my ASP.NET Core MVC (2.2) app I have completed the setup for a global error handling class. I inject this class in the Startup.cs of my project by using app.UseMiddleware()
right before the app.UseMvc()
. This error handler gets triggered on every exception like it should, however, when I set the Response.StatusCode
to the corresponding code (400, 404, 500) and return the response the Error Page controller doesn't get called. However, if I manually return a BadRequest();
from my controller(s) the Error Page controller gets called.
Is it even possible to trigger error pages from a error handler middle ware class? If so, how can I achieve such behavior?
Here is my Error Handling Middle ware Class.
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);
}
}
My Startup configuration
public void Configure(
IApplicationBuilder app,
IHostingEnvironment environment,
ILogger<Startup> logger,
ILoggerFactory factory)
{
app.UseExceptionHandler("/Error");
app.UseStatusCodePagesWithReExecute("/Error/StatusCode/{0}");
// ....
// ....
app.UseMiddleware(typeof(ErrorHandlingMiddleware));
app.UseMvc();
}
Error Page controller
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);
}
}
Controller I am using for testing
public class DummyController : Controller
{
[Route("Dummy")]
public IActionResult Dummy()
{
throw new CommonApiException("Test Error");
//return this.BadRequest(); //This triggers the error page controller.
}
}
Solution 1:[1]
Is it even possible to trigger error pages from a error handler middle ware class? If so, how can I achieve such behavior?
Yes.Try to modify your HandleExceptionAsync
ErrorHandlingMiddleware
to rewrite your 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;
context.SetEndpoint(null);
await this.nextDelegate(context);
return;
}
catch (Exception ex2)
{
}
finally
{
context.Request.Path = originalPath;
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | nZeus |