ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

C# MVC 跨框架异常处理对比:.NET Framework 与 .NET Core 实现差异(附代码+避坑指南)

C# MVC 跨框架异常处理对比:.NET Framework 与 .NET Core 实现差异(附代码+避坑指南) C# MVC 跨框架异常处理对比.NET Framework 与 .NET Core 实现差异附代码避坑指南目录C# MVC 跨框架异常处理对比.NET Framework 与 .NET Core 实现差异附代码避坑指南一、前言为什么要区分两代框架的异常处理二、核心机制总览通俗类比流程图2.1 生活化类比2.2 两代框架异常处理执行流程图.NET Framework MVC 异常流程.NET Core MVC 异常流程2.3 核心本质差异总结三、.NET Framework MVC 异常处理原生实现完整代码3.1 完整自定义异常过滤器代码3.2 全局注册过滤器3.3 web.config 必要配置必须开启3.4 本框架专属特点四、.NET Core/.NET6 MVC 异常处理全新实现完整代码4.1 最优方案全局异常中间件全覆盖、无遗漏4.2 中间件全局注册Program.cs4.3 补充方案Core 异常过滤器局部精细化拦截4.4 Core 框架专属特点五、两代框架核心差异对照表一目了然六、高频踩坑指南90%开发者中招的问题6.1 Framework 框架专属坑6.2 Core 框架专属坑七、项目最佳实践总结7.1 .NET Framework 老旧项目7.2 .NET Core 新项目八、读者互动投票九、结尾复盘本文定位资深开发实战总结零基础可读懂、中级能避坑、高级能复盘。全程附带可运行源码、核心流程图、高频踩坑清单彻底搞懂两代MVC异常处理的底层区别与最佳实践。适用人群.NET 转型开发者、MVC 项目维护者、面试备考、架构优化人员阅读收获彻底分清.NET Framework MVC与.NET Core MVC异常处理机制本质差异掌握两套框架原生异常拦截代码实现规避90%开发者都会踩的跨框架异常坑学会统一全局异常处理、自定义异常、前端友好返回的标准写法一、前言为什么要区分两代框架的异常处理在日常开发中异常处理就相当于程序的“应急保安系统”程序报错时不直接崩溃、不抛出黄页/500空白页而是统一拦截、记录日志、返回友好提示保证系统稳定性。很多开发者从NET Framework 4.x MVC5转型.NET Core/.NET 5 MVC时会直接照搬旧框架的异常代码最终出现异常拦截失效、日志丢失、全局过滤器不生效、API与视图异常冲突等诡异问题。核心原因两代框架的HTTP管道、过滤器执行顺序、异常捕获机制完全重构并非简单升级。二、核心机制总览通俗类比流程图2.1 生活化类比.NET Framework MVC老式小区保安室异常拦截是楼层分片管理只能拦截控制器内异常管道外异常管不到权限有限、漏洞较多。.NET Core MVC新式全域智能安保系统管道全局托管从请求进入到响应结束全链路监控所有异常统一兜底管控范围全覆盖。2.2 两代框架异常处理执行流程图.NET Framework MVC 异常流程是否HTTP请求进入IIS管道预处理进入MVC路由执行控制器Action是否抛出异常触发HandleErrorAttribute过滤器返回自定义错误视图/响应正常返回结果请求结束限制仅拦截Action内异常路由、管道、模型绑定异常无法拦截.NET Core MVC 异常流程任意阶段异常无异常HTTP请求进入内置中间件管道全局异常中间件兜底MVC过滤器层补充拦截执行控制器Action是否抛出异常全局中间件优先捕获统一日志统一响应正常返回结果请求结束优势全链路拦截覆盖管道、路由、模型绑定、Action、结果执行所有阶段2.3 核心本质差异总结拦截载体不同Framework 靠HandleErrorAttribute特性过滤器Core 靠IExceptionFilter 全局中间件双兜底拦截范围不同Framework 仅控制器Action内部异常Core 全请求生命周期所有异常执行优先级不同Framework 过滤器单层执行Core 中间件优先级高于过滤器配置方式不同Framework 全局注册web.config配置Core 依赖DI中间件注册无配置文件约束三、.NET Framework MVC 异常处理原生实现完整代码框架版本MVC5 .NET Framework 4.5/4.8核心实现自定义全局异常过滤器继承HandleErrorAttribute3.1 完整自定义异常过滤器代码usingSystem;usingSystem.Web.Mvc;namespaceFrameworkMVC.Filter{/// summary/// .NET Framework MVC 全局异常处理器/// /summarypublicclassGlobalExceptionFilter:HandleErrorAttribute{publicoverridevoidOnException(ExceptionContextfilterContext){// 1. 判断是否已经处理过异常避免重复拦截if(filterContext.ExceptionHandled)return;// 2. 获取异常信息ExceptionexfilterContext.Exception;stringcontrollerNamefilterContext.RouteData.Values[controller]?.ToString();stringactionNamefilterContext.RouteData.Values[action]?.ToString();// 3. 模拟日志记录项目中替换为Log4Net/NLogConsole.WriteLine($【Framework全局异常】时间{DateTime.Now});Console.WriteLine($控制器{controllerName}方法{actionName});Console.WriteLine($异常信息{ex.Message}堆栈{ex.StackTrace});// 4. 判断是否为AJAX请求区分返回格式boolisAjaxfilterContext.HttpContext.Request.IsAjaxRequest();if(isAjax){// API请求返回JSON错误信息filterContext.ResultnewJsonResult{Datanew{code500,msg服务器异常请稍后重试,data},JsonRequestBehaviorJsonRequestBehavior.AllowGet};}else{// 页面请求跳转自定义错误页filterContext.ResultnewViewResult{ViewName~/Views/Shared/Error.cshtml};}// 5. 标记异常已处理核心必须加否则会走系统黄页filterContext.ExceptionHandledtrue;}}}3.2 全局注册过滤器在App_Start/FilterConfig.cs注册全局生效usingSystem.Web.Mvc;namespaceFrameworkMVC{publicclassFilterConfig{publicstaticvoidRegisterGlobalFilters(GlobalFilterCollectionfilters){// 移除默认异常过滤器使用自定义全局异常filters.RemoveAll(typeof(HandleErrorAttribute));filters.Add(newGlobalExceptionFilter());}}}3.3 web.config 必要配置必须开启Framework 必须开启自定义错误否则过滤器失效system.webcustomErrorsmodeOndefaultRedirect~/Views/Shared/Error.cshtmlerrorstatusCode404redirect~/Views/Shared/404.cshtml//customErrors/system.web3.4 本框架专属特点仅能拦截Action执行内部抛出的异常模型绑定异常、路由匹配失败、IIS管道异常无法拦截必须配置customErrors节点否则自定义错误页不生效AJAX请求和普通页面请求需要手动区分处理四、.NET Core/.NET6 MVC 异常处理全新实现完整代码Core 彻底抛弃了 Framework 的老旧机制采用中间件优先、过滤器补充的双方案推荐优先使用全局异常中间件覆盖所有场景。4.1 最优方案全局异常中间件全覆盖、无遗漏usingMicrosoft.AspNetCore.Http;usingSystem;usingSystem.Threading.Tasks;namespaceCoreMVC.Middleware{/// summary/// .NET Core 全局异常中间件全链路拦截/// /summarypublicclassGlobalExceptionMiddleware{privatereadonlyRequestDelegate_next;publicGlobalExceptionMiddleware(RequestDelegatenext){_nextnext;}publicasyncTaskInvokeAsync(HttpContextcontext){try{// 执行后续请求管道await_next(context);}catch(Exceptionex){// 捕获管道所有阶段异常路由、模型绑定、Action、结果渲染awaitHandleExceptionAsync(context,ex);}}/// summary/// 统一异常响应处理/// /summaryprivatestaticasyncTaskHandleExceptionAsync(HttpContextcontext,Exceptionex){// 1. 设置响应格式context.Response.ContentTypeapplication/json;context.Response.StatusCodeStatusCodes.Status500InternalServerError;// 2. 日志记录替换为Serilog/NLogConsole.WriteLine($【Core全局异常】{DateTime.Now}| 异常{ex.Message}| 堆栈{ex.StackTrace});// 3. 区分自定义业务异常与系统异常varresultexswitch{// 自定义业务异常返回前端友好提示BusinessExceptionbizExnew{codebizEx.Code,msgbizEx.Message,data},// 系统未知异常隐藏详细信息_new{code500,msg系统繁忙请稍后重试,data}};// 4. 返回统一JSON响应awaitcontext.Response.WriteAsJsonAsync(result);}}// 自定义业务异常类publicclassBusinessException:Exception{publicintCode{get;set;}publicBusinessException(intcode,stringmsg):base(msg){Codecode;}}}4.2 中间件全局注册Program.cs.NET6 极简顶层语句注册必须放在所有中间件最前方varbuilderWebApplication.CreateBuilder(args);// 注册MVC控制器builder.Services.AddControllersWithViews();varappbuilder.Build();// 全局异常中间件优先级最高全链路兜底app.UseMiddlewareGlobalExceptionMiddleware();if(!app.Environment.IsDevelopment()){app.UseExceptionHandler(/Home/Error);}app.UseStaticFiles();app.UseRouting();app.UseAuthorization();app.MapControllerRoute(name:default,pattern:{controllerHome}/{actionIndex}/{id?});app.Run();4.3 补充方案Core 异常过滤器局部精细化拦截适用于需要仅拦截控制器异常、单独处理的场景作为中间件的补充usingMicrosoft.AspNetCore.Mvc;usingMicrosoft.AspNetCore.Mvc.Filters;namespaceCoreMVC.Filter{publicclassCoreExceptionFilter:IExceptionFilter{publicvoidOnException(ExceptionContextcontext){if(context.ExceptionHandled)return;// 控制器内异常处理逻辑context.ResultnewJsonResult(new{code500,msg控制器执行异常});context.ExceptionHandledtrue;}}}4.4 Core 框架专属特点中间件可拦截请求全生命周期所有异常无死角无需配置文件完全依赖DI管道注册支持自定义异常分级处理业务异常、系统异常分离中间件优先级高于过滤器优先兜底全局异常五、两代框架核心差异对照表一目了然对比维度.NET Framework MVC5.NET Core MVC核心实现方式继承 HandleErrorAttribute 过滤器全局异常中间件 IExceptionFilter 双方案异常拦截范围仅控制器Action内部异常路由、模型绑定、Action、管道全链路异常配置依赖必须开启web.config customErrors无配置文件依赖管道注册即可AJAX/页面区分需手动判断请求类型可统一JSON返回自动适配前后端异常兜底能力弱存在大量拦截盲区强全链路无死角兜底适用场景老旧项目维护新项目开发、微服务、前后端分离六、高频踩坑指南90%开发者中招的问题6.1 Framework 框架专属坑坑1忘记开启 customErrors 节点现象自定义异常过滤器不生效报错直接显示系统黄页。原因Framework 异常拦截依赖配置文件开关默认关闭。解决必须在web.config开启 mode“On”。坑2无法拦截模型绑定、路由异常现象参数格式错误、路由不存在报错全局过滤器无日志、无拦截。解决Framework 原生机制缺陷无法根治只能额外写IIS错误页兜底。坑3未标记 ExceptionHandledtrue现象异常处理后依然弹出系统错误页重复报错。解决处理完异常必须手动标记为已处理。6.2 Core 框架专属坑坑1中间件注册位置靠后现象部分异常拦截失效日志丢失。原因Core 中间件执行顺序从上到下异常中间件必须放在最前方。坑2照搬Framework 过滤器写法现象全局异常拦截不全盲区较多。原因Core 优先中间件过滤器仅作为补充不能作为主力方案。坑3开发环境开启自定义错误现象开发时看不到详细报错堆栈不利于调试。解决开发环境禁用自定义错误生产环境开启。七、项目最佳实践总结7.1 .NET Framework 老旧项目使用自定义HandleErrorAttribute作为全局异常核心务必开启 web.config customErrors 配置手动区分AJAX和页面请求适配前后端场景额外增加IIS错误页兜底路由、管道异常盲区7.2 .NET Core 新项目优先使用全局异常中间件实现全链路兜底自定义业务异常类区分业务报错和系统报错配合Serilog/NLog记录详细异常日志、请求参数过滤器仅作为局部控制器异常精细化处理补充八、读者互动投票看完本文欢迎参与投票看看大家的开发习惯投票选项A. 一直用Framework过滤器从未发现拦截盲区B. Core项目只用过滤器踩过拦截不全的坑C. Core项目优先中间件标准最佳实践D. 之前完全分不清两代框架差异现在彻底懂了九、结尾复盘两代.NET MVC异常处理的核心差异本质是管道架构的升级从Framework的“分片局部拦截”升级为Core的“全局全链路拦截”。很多诡异的异常问题并不是代码写错了而是用旧框架的思维写新框架的代码。掌握本文的代码实现和避坑要点可以彻底解决MVC项目99%的异常处理问题适配老旧项目维护和新项目开发所有场景。我是专注.NET实战的博主持续分享落地性极强的.NET进阶干货点赞收藏不迷路下期分享.NET 全局日志统一落地方案
返回列表