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

.Net Core MVC如何重写OnException实现异常过滤器统一错误处理

自定义异常过滤器实现方案

你可以按照以下逻辑重写OnException方法,完全替代Action内重复的try-catch错误处理逻辑:

核心实现逻辑

  • 优先判断异常是否已被其他逻辑处理,避免重复执行错误响应
  • 区分运行环境,开发环境返回完整异常信息方便排查,生产环境隐藏敏感错误详情
  • 实例化你预先定义的错误模型,填充请求ID、请求路径、异常信息等字段
  • 替换请求返回结果为错误视图,传入填充完成的错误模型
  • 标记异常为已处理状态,设置对应HTTP状态码

具体代码实现

首先定义自定义异常过滤器,如果你需要把过滤器作为特性标记到单独的Controller/Action上,就继承ExceptionFilterAttribute,如果只做全局过滤器,实现IExceptionFilter接口即可:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;

public class GlobalExceptionFilter : ExceptionFilterAttribute
{
    private readonly IWebHostEnvironment _webHostEnv;

    // 注入运行环境,用于区分开发/生产环境
    public GlobalExceptionFilter(IWebHostEnvironment webHostEnv)
    {
        _webHostEnv = webHostEnv;
    }

    public override void OnException(ExceptionContext context)
    {
        // 异常已被处理则直接跳过
        if (context.ExceptionHandled)
        {
            return;
        }

        // 填充你定义好的错误模型,这里假设你的错误模型类名为ErrorViewModel
        var errorInfo = new ErrorViewModel
        {
            RequestId = context.HttpContext.TraceIdentifier,
            RequestPath = context.HttpContext.Request.Path,
            // 开发环境返回真实异常信息,生产环境返回通用提示
            ErrorMsg = _webHostEnv.IsDevelopment() ? context.Exception.Message : "服务繁忙,请稍后再试",
            // 开发环境返回堆栈信息方便排查,生产环境置空避免泄露敏感信息
            StackTrace = _webHostEnv.IsDevelopment() ? context.Exception.StackTrace : string.Empty
        };

        // 构造视图返回结果,替换原有异常响应
        context.Result = new ViewResult
        {
            // 替换为你实际开发的错误视图路径
            ViewName = "~/Views/Shared/Error.cshtml",
            ViewData = new ViewDataDictionary<ErrorViewModel>(new EmptyModelMetadataProvider(), context.ModelState)
            {
                Model = errorInfo
            }
        };

        // 设置响应状态码为500服务端错误
        context.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
        // 标记异常已处理,阻止后续异常处理逻辑触发
        context.ExceptionHandled = true;
    }
}

过滤器注册

如果需要全局生效(覆盖所有Action请求,完全替代你原来每个Action写的try-catch),在Program.cs中注册为全局过滤器即可:

builder.Services.AddControllersWithViews(opt =>
{
    opt.Filters.Add<GlobalExceptionFilter>();
});

如果只需要给特定Controller或Action生效,直接在对应类/方法上标记[GlobalExceptionFilter]特性即可。

注意事项

  • 生产环境务必屏蔽完整异常信息、堆栈内容,避免泄露代码结构、数据库连接串等敏感信息
  • 如果项目同时包含MVC视图接口和WebApi接口,可以在方法内增加请求类型判断:Ajax/Api请求返回JSON格式错误结果,视图请求返回错误页,避免前端收到HTML内容解析异常
  • 可以在异常处理逻辑中增加日志埋点,将异常信息写入日志系统方便后续排查问题

内容的提问来源于stack exchange,提问作者ogiyavuz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 15:12:20