ASP.NET MVC异常处理方案
异常处理是每一个系统都必须要有的功能,尤其对于Web系统而言,简单、统一的异常处理模式尤为重要,当打算使用ASP.NET MVC来做项目时,第一个数据录入页面就遇到了这个问题。
在之前的ASP.NET WebForm项目中,一般情况下都是在Application_Error事件处理器和ScriptManager_AsyncPostBackError事件处理器里面进行,在ASP.NET MVC中用这两种方法似乎都不合适了,该放在哪儿呢?总不至于在每个Action里面都放一个try{...}catch{...}吧。
在ScottGu的博客里面提到了一个类:HandleErrorAttribute,似乎是用于处理异常的,于是使用HandleErrorAttribute来做个尝试,(说明,如果使用了该类型,并且想把异常显示在自已指定的View,则必须在web.config里面的<system.web>节点加上<customErrors mode="On" />)发现HandleError的确比较好用,可以使用其View属性指定异常后跳转的页面,可以针对不同的异常类型跳到不同的异常显示View,而且也可以不跳转到异常显示View,显示到当前View,例:
[HttpPost][HandleError(View = "Create", ExceptionType = typeof(Exception))]public ActionResult Create(string someParam){ throw new Exception("oops...");} |
当异常发生时,页面还会跳回到Create,只是这里有点小问题,用户在页面上输入了很多东西,你提示个异常不至于把他辛辛苦苦输了半天的东西都没有了吧,把这样的项目送出去,迟早是要改回来的。
打开HandleErrorAttribute的源代码可以看其关键部分:
public virtual void OnException(ExceptionContext filterContext) { if (filterContext == null) { throw new ArgumentNullException("filterContext"); } if (filterContext.IsChildAction) { return; } // If custom errors are disabled, we need to let the normal ASP.NET exception handler // execute so that the user can see useful debugging information. if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled) { return; } Exception exception = filterContext.Exception; // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method), // ignore it. if (new HttpException(null, exception).GetHttpCode() != 500) { return; } if (!ExceptionType.IsInstanceOfType(exception)) { return; } string controllerName = (string)filterContext.RouteData.Values["controller"]; string actionName = (string)filterContext.RouteData.Values["action"]; HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName); filterContext.Result = new ViewResult { ViewName = View, MasterName = Master, ViewData = new ViewDataDictionary<HandleErrorInfo>(model), TempData = filterContext.Controller.TempData }; filterContext.ExceptionHandled = true; filterContext.HttpContext.Response.Clear(); filterContext.HttpContext.Response.StatusCode = 500; // Certain versions of IIS will sometimes use their own error page when // they detect a server error. Setting this property indicates that we // want it to try to render ASP.NET MVC's error page instead. filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;} |
可以很清楚的看到,MVC实际上是使用刚才我们指定的View名称新建了一个ViewResult,然后将这个ViewResult交给了InvokeActionResult方法,最终显示给了用户。在这个过程中,新的ViewResult的ViewData被设定为HandleErrorInfo了,没有将Create上的数据放进ViewData,尽管在之后显示的Create视图的Request里还保存着之前的Params内容,但是数据却没有加载上去,我也没有去深究,感觉如果在这里直接把filterContext.Controller中的ViewData直接作为新的ViewResult的ViewData的话,肯定是可以显示提交之前的数据的(因为如果将异常代码包在try...catch...里面是可以在异常后显示之前数据的)。
于是自已新建一个ExceptionFitler:
public class CustomHandleErrorAttribute : FilterAttribute, IExceptionFilter{ public void OnException(ExceptionContext filterContext) { filterContext.Controller.ViewData["Exception"] = filterContext.Exception; filterContext.Result = new ViewResult() { ViewName = filterContext.Controller.ControllerContext.RouteData.Values["Action"].ToString(), ViewData = filterContext.Controller.ViewData }; filterContext.ExceptionHandled = true; filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; }} |
类名起的不咋的,将就着用吧:)
将原来的Action修改如下:
[HttpPost][CustomHandleError]public ActionResult Create(string Name){ throw new Exception("oops...");} |
Create.csthml中加入如下代码:
if (ViewData["Exception"] != null){ var ex = ViewData["Exception"] as Exception; @ex.Message} |
F5,果然在提交后又回到了原来视图,而且之前填写的数据都还在。
3月19日完善如下:-----------------------------------------
namespace System.Web.Mvc{ public class HandleExceptionAttribute : HandleErrorAttribute, IExceptionFilter { #region IExceptionFilter Members public override void OnException(ExceptionContext filterContext) { if (filterContext == null) { throw new ArgumentNullException("filterContext"); } if (filterContext.IsChildAction) { return; } // If custom errors are disabled, we need to let the normal ASP.NET exception handler // execute so that the user can see useful debugging information. if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled) { return; } Exception exception = filterContext.Exception; // If this is not an HTTP 500 (for example, if somebody throws an HTTP 404 from an action method), // ignore it. if (new HttpException(null, exception).GetHttpCode() != 500) { return; } if (!ExceptionType.IsInstanceOfType(exception)) { return; } string actionName = (string)filterContext.RouteData.Values["action"]; filterContext.Controller.ViewData["Exception"] = exception; filterContext.Result = new ViewResult() { ViewName = actionName, ViewData = filterContext.Controller.ViewData }; filterContext.ExceptionHandled = true; filterContext.HttpContext.Response.Clear(); filterContext.HttpContext.Response.StatusCode = 500; filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; } #endregion } public static class HandleExceptionHelper { public static Exception Exception(this HtmlHelper htmlhelper) { var exception = htmlhelper.ViewContext.Controller.ViewData["Exception"] as Exception; return exception; } }} |
View运用如下:
if (@Html.Exception() != null){ @Html.Exception().Message} |
3月20日添加生成jQuery错误样式:------------------------------------------------
public static class HandleExceptionHelper{ public static Exception Exception(this HtmlHelper htmlhelper) { var exception = htmlhelper.ViewContext.Controller.ViewData["Exception"] as Exception; return exception; } public static MvcHtmlString jQueryStyleError(this HtmlHelper htmlhelper) { var exception = Exception(htmlhelper); if (exception == null) { return null; } TagBuilder builder = new TagBuilder("div"); builder.GenerateId("editordescription"); builder.AddCssClass("ui-widget ui-state-error ui-corner-all"); builder.InnerHtml = string.Format(@"<p><span class=""ui-icon ui-icon-alert"" style=""float: left; margin-right: .3em;""></span><strong>{0}: </strong>{1}</p>", Resx.Error, string.IsNullOrEmpty(exception.Message) ? Resx.UnknowErrorMessage : exception.Message); return new MvcHtmlString(builder.ToString(TagRenderMode.Normal)); }} |
View应用如下:
@Html.jQueryStyleError() |
效果如下:

ASP.NET MVC异常处理方案的更多相关文章
- ASP.NET MVC异常处理
ASP.NET MVC异常处理方案 如何保留异常前填写表单的数据 ASP.NET MVC中的统一化自定义异常处理 MVC过滤器详解 MVC过滤器使用案例:统一处理异常顺道精简代码 ASP.NET MV ...
- 一个简单的ASP.NET MVC异常处理模块
一.前言 异常处理是每个系统必不可少的一个重要部分,它可以让我们的程序在发生错误时友好地提示.记录错误信息,更重要的是不破坏正常的数据和影响系统运行.异常处理应该是一个横切点,所谓横切点就是各个部分都 ...
- ASP.NET mvc异常处理的方法
第一种:全局异常处理 1.首先常见保存异常的类(就是将异常信息写入到文件中去) public class LogManager { private string logFilePath = strin ...
- ASP.NET MVC Anti-XSS方案
1:Form提交模式 在使用Form提交时,MVC框架提供了一个默认的机制.如果数据中含有恶意字,则会自动转向出错页面. 2:Ajax+JSON提交模式. MVC框架未提供对于Json数据的Ant ...
- asp.net MVC 异常处理
http://www.cnblogs.com/think8848/archive/2011/03/18/1987849.html http://www.cnblogs.com/snowdream/ar ...
- NET MVC异常处理模块
一个简单的ASP.NET MVC异常处理模块 一.前言 异常处理是每个系统必不可少的一个重要部分,它可以让我们的程序在发生错误时友好地提示.记录错误信息,更重要的是不破坏正常的数据和影响系统运行. ...
- ASP.NET MVC 多语言方案
前言: 好多年没写文章了,工作很忙,天天加班, 每天都相信不用多久,就会升职加薪,当上总经理,出任CEO,迎娶白富美,走上人生巅峰,想想还有点小激动~~~~ 直到后来发生了邮箱事件,我竟然忘了给邮箱密 ...
- 七天学会ASP.NET MVC (六)——线程问题、异常处理、自定义URL
本节又带了一些常用的,却很难理解的问题,本节从文件上传功能的实现引出了线程使用,介绍了线程饥饿的解决方法,异常处理方法,了解RouteTable自定义路径 . 系列文章 七天学会ASP.NET MVC ...
- Asp.net Mvc 身份验证、异常处理、权限验证(拦截器)实现代码
本问主要介绍asp.net的身份验证机制及asp.net MVC拦截器在项目中的运用.现在让我们来模拟一个简单的流程:用户登录>权限验证>异常处理 1.用户登录 验证用户是否登录成功步骤直 ...
随机推荐
- Python2.7-weakref
weakref 模块,允许创建对象的弱引用,被弱引用的对象其引用计数不变,对象的引用计数为0时就会被垃圾清理机制释放内存空间,此时对其的弱引用也会失效.在对象会被交叉引用,需要释放内存空间时常用. 模 ...
- 学习笔记---gson
1.gson变量定义注解 @SerializedName("char") private String charm;//mongo转化char 2.gson中json文件转化成类 ...
- 【甘道夫】CDH5.2的Maven依赖
之前一直结合Maven开发Hadoop2.2.0的程序.环境换成CDH5.2后报错,发现是Maven依赖库的问题. 之前一直使用 http://mvnrepository.com/ 查找maven依赖 ...
- 查看Oracle数据库中的,已经连接好的..当前用户状况
参考: http://stackoverflow.com/questions/1043096/how-to-list-active-open-connections-in-oracle 以sys身份连 ...
- 双面间谍(spy)
双面间谍 链接 分析: 戳这 代码: #include<cstdio> #include<algorithm> #include<cstdio> #include& ...
- libgdx学习记录17——照相机Camera
照相机在libgdx中的地位举足轻重,贯穿于整个游戏开发过程的始终.一般我们都通过Stage封装而间接使用Camera,同时我们也可以单独使用Camera以完成背景的移动.元素的放大.旋转等操作. C ...
- 表单设置 disabled 后无法传值到后台的解决办法
在提交 from 表单时,下面的 input 无法正常提交给后台, 发现,如果input的字段设为disabled,该表单是无法提交的. <input type="text" ...
- HDFS-异常大全-《每日五分钟搞定大数据》
点击看<每日五分钟搞定大数据>完整思维导图以及所有文章目录 问题1:Decomminssioning退役datanode(即删除节点) 1.配置exclude: <name>d ...
- C# Language Specification 5.0 (翻译)第二章 词法结构
程序 C# 程序(program)由至少一个源文件(source files)组成,其正式称谓为编译单元(compilation units)[1].每个源文件都是有序的 Unicode 字符序列.源 ...
- C语言与数据库操作入门(Win版)
C语言与数据库操作入门(Win版) 2017年12月10日 17:30:17 阅读数:1387 数据库,DataBase,学C语言的是不是想说,很想爱她却并不容易呢?不用着急,C语言也可以操作数据库的 ...