Reputation: 69
I'm looking to redirect HTTP requests with 4XX or 5XX error code to a custom error page, while keeping the error code at the request level. I also want to redirect exceptions to a custom error page, with an error code 500.
For that I used in my Startup file "app.UseStatusCodePagesWithReExecute("/error/{0}"); app.UseExceptionHandler("/error/500");" associated with an Error controller.
The part about exceptions works well. I also manage to redirect non-existent routes to my custom page while keeping the 404 error.
However, I can't redirect the following actions to my custom error pages:
What would be the technical solution applied to accomplish this?
Here is the Configure function of my Startup file :
app.UseStatusCodePagesWithReExecute("/error/{0}");
app.UseExceptionHandler("/error/500");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "Error-StatusCode-Route",
pattern: "error/{statusCode}",
defaults: new { controller = "Error", action = "InternalServerError" }
);
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
Upvotes: 1
Views: 919
Reputation: 1697
If you are using core3, then this is a known bug. This bug will be fixed in 3.1. Here is a link to the issue: https://github.com/aspnet/AspNetCore/issues/13715
For now there is a workaround. You can add this code right after you call app.UseStatusCodePagesWithReExecute("/error/{0}");
app.Use((context, next) =>
{
context.SetEndpoint(null);
return next();
});
This will render your custom pages when you return NotFound or BadRequest from your controller action.
Upvotes: 0
Reputation: 36655
You could custom middleware to deal with it:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseStatusCodePagesWithReExecute("/error/{0}");
app.UseExceptionHandler("/error/500");
app.Use(async (context, next) =>
{
await next();
var code = context.Response.StatusCode;
var newPath = new PathString("/error/"+code);
var originalPath = context.Request.Path;
var originalQueryString = context.Request.QueryString;
context.Features.Set<IStatusCodeReExecuteFeature>(new StatusCodeReExecuteFeature()
{
OriginalPathBase = context.Request.PathBase.Value,
OriginalPath = originalPath.Value,
OriginalQueryString = originalQueryString.HasValue ? originalQueryString.Value : null,
});
// An endpoint may have already been set. Since we're going to re-invoke the middleware pipeline we need to reset
// the endpoint and route values to ensure things are re-calculated.
context.SetEndpoint(endpoint: null);
var routeValuesFeature = context.Features.Get<IRouteValuesFeature>();
routeValuesFeature?.RouteValues?.Clear();
context.Request.Path = newPath;
try
{
await next();
}
finally
{
context.Request.QueryString = originalQueryString;
context.Request.Path = originalPath;
context.Features.Set<IStatusCodeReExecuteFeature>(null);
}
});
app.UseHttpsRedirection();
app.UseStaticFiles();
//...
}
For your ErrorController:
public class ErrorController : Controller
{
// GET: /<controller>/
public IActionResult InternalServerError()
{
return View();
}
[Route("error/404")]
public IActionResult StatusCode404()
{
//redirect to the StatusCode404.cshtml
return View();
}
[Route("error/400")]
public IActionResult StatusCode400()
{
return View();
}
}
Upvotes: 1