You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 02:00:33