.NET 6 Razor Pages如何捕获框架异常并返回自定义错误页
在.NET 6 Razor Pages中捕获Multipart上传超限及Antiforgery错误并返回自定义错误页
一、问题根源梳理
- Multipart上传超限错误发生在表单解析阶段(ASP.NET Core管道早期),早于Razor Pages中间件执行,因此常规的
UseExceptionHandler无法捕获该异常。 - Antiforgery验证错误在Action执行前触发,部分场景下不会被常规异常处理机制捕获,直接返回通用400状态码。
二、分步解决方案
1. 捕获Multipart上传超限错误
通过自定义中间件提前触发表单解析,主动捕获InvalidDataException,并将错误信息传递给自定义错误页:
步骤1:添加全局捕获中间件
在Program.cs中,将该中间件放在UseExceptionHandler之后、UseRouting之前:
app.UseExceptionHandler("/Error"); // 捕获Multipart上传超限的自定义中间件 app.Use(async (context, next) => { try { // 仅对multipart/form-data类型请求提前解析表单 if (!string.IsNullOrEmpty(context.Request.ContentType) && context.Request.ContentType.StartsWith("multipart/form-data", StringComparison.OrdinalIgnoreCase)) { await context.Request.ReadFormAsync(); } await next(); } catch (InvalidDataException ex) when (ex.Message.Contains("Multipart body length limit exceeded")) { // 将错误信息存入HttpContext.Items,供错误页读取 context.Items["CustomErrorMessage"] = "上传文件过大,已超出系统允许的大小上限,请上传更小的文件。"; context.Response.StatusCode = StatusCodes.Status400BadRequest; // 让后续状态码页中间件处理重定向 await next(); } }); app.UseStatusCodePagesWithReExecute("/Error/{0}"); app.UseRouting(); // ... 其他中间件(UseAuthorization、UseRazorPages等)
2. 处理Antiforgery验证错误
通过配置AntiforgeryOptions的OnValidationFailed回调,直接注入错误信息并跳转错误页:
步骤1:配置Antiforgery服务
在Program.cs的服务注册阶段添加:
builder.Services.AddAntiforgery(options => { options.OnValidationFailed = context => { context.HttpContext.Items["CustomErrorMessage"] = "请求验证失败,请刷新页面后重新尝试提交表单。"; context.HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest; // 重定向到错误页路由 context.HttpContext.Request.Path = "/Error/400"; return Task.CompletedTask; }; });
3. 自定义错误页展示详情
修改Razor Pages的Error.cshtml.cs,读取HttpContext.Items中的错误信息并展示:
public class ErrorModel : PageModel { public string? ErrorMessage { get; set; } public int? StatusCode { get; set; } public void OnGet(int? statusCode) { StatusCode = statusCode; // 读取自定义错误信息 if (HttpContext.Items.ContainsKey("CustomErrorMessage")) { ErrorMessage = HttpContext.Items["CustomErrorMessage"] as string; } else { // 默认错误提示 ErrorMessage = StatusCode switch { 400 => "请求参数错误,请检查后重试。", 500 => "服务器内部错误,请稍后再试。", _ => "发生未知错误,请联系管理员。" }; } } }
对应的Error.cshtml页面渲染示例:
@page @model ErrorModel @{ ViewData["Title"] = "错误"; } <h1 class="text-danger">错误 @Model.StatusCode</h1> <div class="alert alert-danger"> @Model.ErrorMessage </div> <a asp-page="/Index" class="btn btn-primary">返回首页</a>
三、关键注意事项
- 中间件顺序至关重要:捕获Multipart异常的中间件必须放在
UseRouting之前、UseExceptionHandler之后,确保能在表单解析阶段捕获异常。 UseStatusCodePagesWithReExecute用于将状态码请求重定向到错误页,替代默认的空白400页面。- 通过
HttpContext.Items传递错误信息,是管道间传递上下文数据的轻量方式,避免直接硬编码响应内容。
内容的提问来源于stack exchange,提问作者Vincent
相关产品推荐
相关产品推荐

