ASP.NET Core MVC中UseStatusCodePagesWithReExecute状态码传0问题
ASP.NET Core 7 MVC自定义错误页面状态码传递异常问题
问题描述
在为ASP.NET Core 7 MVC + ASP.NET MVC 5实现404、500错误自定义处理逻辑时,已配置错误控制器及视图,尝试使用UseStatusCodePagesWithReExecute中间件,但错误控制器始终收到状态码0,而非实际的HTTP状态码(如404)。
相关代码
Program.cs
var builder = WebApplication.CreateBuilder(args); // Add services to the container. // MVC if (builder.Environment.IsDevelopment()) builder.Services.AddControllersWithViews().AddRazorRuntimeCompilation(); //for debugging views else builder.Services.AddControllersWithViews(); // Add services to the container. // Blazor builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor() .AddHubOptions(options => { options.ClientTimeoutInterval = TimeSpan.FromSeconds(30); options.EnableDetailedErrors = false; options.HandshakeTimeout = TimeSpan.FromSeconds(15); options.KeepAliveInterval = TimeSpan.FromSeconds(15); options.MaximumParallelInvocationsPerClient = 1; options.MaximumReceiveMessageSize = 32 * 1024; options.StreamBufferCapacity = 10; }); //Mudblazor UI Lib //builder.Services.AddMudServices(); //connstring configs builder.Services.Configure<AppSettings>( builder.Configuration.GetSection("ConnectionStrings")); //EF registrations builder.Services.AddDbContext<ArticlesContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("ArticleDBconnectionString"))); builder.Services.AddDbContext<ProductContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("ProductsConnection"))); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } //app.UseStatusCodePages(); app.UseStatusCodePagesWithReExecute("/Error/{0}"); app.UseMiddleware<ViewNotFoundExceptionMiddleware>(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); //Razor config app.MapRazorPages(); app.MapBlazorHub(); //mvc config app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
ErrorController.cs
[AllowAnonymous] public class ErrorController : Controller { [Route("/Error/{code}")] new public ActionResult NotFound(int StatusCode) { var errorFeature = HttpContext.Features.Get<IExceptionHandlerFeature>(); var error = errorFeature?.Error; ViewBag.ErrorMsg = "404 Page not found please try again XD"; return View("Error", ViewBag); } [Route("/Error")] public ActionResult Error(int StatusCode) { var errorFeature = HttpContext.Features.Get<IExceptionHandlerFeature>(); var error = errorFeature?.Error; ViewBag.ErrorMsg = "500 Server Error please try again XD"; return View(); } }
问题原因及解决方案
1. 路由参数与控制器参数不匹配
UseStatusCodePagesWithReExecute("/Error/{0}")中的{0}会被替换为实际HTTP状态码,传递到路由的占位符中。但你的控制器方法:
- 路由是
/Error/{code},占位符名为code - 方法参数名为
StatusCode
模型绑定无法将code映射到StatusCode,因此参数默认值0被传入。
修正方案:
统一路由占位符名称与方法参数名称,例如:
[Route("/Error/{statusCode}")] public ActionResult StatusCodeError(int statusCode) { ViewBag.ErrorMsg = statusCode switch { 404 => "404 页面未找到,请重试 XD", 500 => "500 服务器错误,请重试 XD", _ => $"HTTP {statusCode} 错误" }; return View("Error"); }
2. 混淆异常处理与状态码处理逻辑
UseStatusCodePagesWithReExecute用于处理非异常导致的HTTP状态码(如路由不存在的404),而IExceptionHandlerFeature仅在UseExceptionHandler的异常处理流程中存在,在状态码处理方法中获取不到该Feature,属于无效逻辑。
修正方案:
拆分控制器方法,分别处理状态码和未捕获异常:
// 处理状态码页面(如404、403) [Route("/Error/{statusCode}")] public ActionResult StatusCodeError(int statusCode) { // 状态码相关逻辑 return View("Error"); } // 处理未捕获异常(由UseExceptionHandler跳转) [Route("/Error")] public ActionResult ExceptionError() { var errorFeature = HttpContext.Features.Get<IExceptionHandlerFeature>(); var error = errorFeature?.Error; ViewBag.ErrorMsg = "服务器发生未处理异常,请重试 XD"; // 可添加日志记录逻辑 return View("Error"); }
3. 中间件顺序错误
UseStatusCodePagesWithReExecute需要放在UseRouting之前,才能正确拦截状态码并重新执行请求。同时自定义的ViewNotFoundExceptionMiddleware可能会提前处理404请求,导致UseStatusCodePagesWithReExecute无法生效。
修正方案:
调整中间件顺序,移除或调整自定义中间件位置:
if (app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); } // 放在UseRouting之前 app.UseStatusCodePagesWithReExecute("/Error/{0}"); // 若自定义中间件需保留,移至UseStatusCodePagesWithReExecute之后 // app.UseMiddleware<ViewNotFoundExceptionMiddleware>(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); // 后续路由映射...
内容的提问来源于stack exchange,提问作者d0rf47
相关产品推荐
相关产品推荐

