ASP.NET Core未用UseDeveloperExceptionPage却出现开发者异常页问题
ASP.NET MVC 自定义错误页异常问题
项目修改说明
这是一个基于模板创建的简单MVC项目,已修改以下文件:
Program.cs
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllersWithViews(); var app = builder.Build(); app.UseExceptionHandler("/Home/Error"); if (!app.Environment.IsDevelopment()) { app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
HomeController.cs(Privacy和Error方法)
public IActionResult Privacy() { throw new Exception("Exception message"); return View(); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { HttpContext.Response.StatusCode = StatusCodes.Status404NotFound; var contextFeature = HttpContext.Features.Get<IExceptionHandlerFeature>(); return View(new ErrorViewModel { Message = contextFeature!.Error.Message }); }
问题描述
项目运行在开发模式(IIS Express)下,访问Privacy方法触发异常后,自定义错误页下方会额外显示开发者异常页,但项目中并未调用UseDeveloperExceptionPage()。该问题仅在Error方法中设置HttpContext.Response.StatusCode = StatusCodes.Status404NotFound时出现,设置其他状态码则能正常显示自定义错误页。
问题原因
- 开发模式下,ASP.NET Core默认中间件对404状态码存在特殊处理逻辑:当响应状态码为404时,即便已通过
UseExceptionHandler处理了异常,后续中间件(如静态文件中间件)仍会尝试查找匹配资源,未找到时会触发默认的开发者404错误页,导致与自定义错误页叠加显示。 - 在Error方法中直接设置404状态码后,响应未被标记为已完成,后续中间件仍能介入处理流程。
解决办法
方法1:修改Error方法,确保响应处理完成
在设置状态码前先清除现有响应,避免后续中间件干扰:
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { var contextFeature = HttpContext.Features.Get<IExceptionHandlerFeature>(); // 清除响应内容,标记响应已开始处理 HttpContext.Response.Clear(); HttpContext.Response.StatusCode = StatusCodes.Status404NotFound; return View(new ErrorViewModel { Message = contextFeature!.Error.Message }); }
方法2:使用NotFound()结果替代手动设置状态码
通过返回NotFoundObjectResult来设置404状态码,ASP.NET Core会自动处理响应完成逻辑:
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { var contextFeature = HttpContext.Features.Get<IExceptionHandlerFeature>(); var model = new ErrorViewModel { Message = contextFeature!.Error.Message }; return NotFound(model); }
需确保Error视图能正常接收并显示ErrorViewModel的数据。
方法3:调整中间件配置,统一处理状态码
在Program.cs中添加UseStatusCodePagesWithReExecute,优先处理状态码异常,同时保持异常处理中间件的优先级:
var app = builder.Build(); // 先添加状态码页面处理 app.UseStatusCodePagesWithReExecute("/Home/Error/{0}"); app.UseExceptionHandler("/Home/Error"); // 其他中间件配置...
然后修改Error方法接收状态码参数:
public IActionResult Error(int? statusCode) { var contextFeature = HttpContext.Features.Get<IExceptionHandlerFeature>(); var model = new ErrorViewModel { Message = contextFeature?.Error?.Message ?? $"状态码: {statusCode}" }; HttpContext.Response.StatusCode = statusCode ?? StatusCodes.Status500InternalServerError; return View(model); }
内容的提问来源于stack exchange,提问作者AynMags
相关产品推荐
相关产品推荐

