MVC异常处理详解

在MVC框架中,异常处理是一个重要的议题。它不仅可以帮助更好地管理程序中的错误,还可以提高用户体验。本文将详细讨论MVC中的异常处理机制,包括本地级别的异常处理和全局级别的异常处理。

实验环境搭建

在开始异常处理的演示之前,需要创建一个示例项目。这将帮助更好地理解异常处理的工作原理和实现方式。

本地级别的异常处理

本地级别的异常处理通常涉及到在控制器的每个动作方法中使用try-catch块。以下是一个简单的例子: public ActionResult TestMethod() { try { // 业务逻辑代码 return View(); } catch (Exception e) { // 异常处理逻辑 return View("Error"); } } 这种方式的问题在于,不能在多个动作方法之间重用异常处理逻辑。为了解决这个问题,可以使用控制器的OnException方法。

控制器级别的异常处理

覆盖控制器的OnException方法可以让在整个控制器的所有动作方法中共享异常处理逻辑。以下是如何实现的示例: protected override void OnException(ExceptionContext filterContext) { Exception e = filterContext.Exception; // 记录异常 filterContext.ExceptionHandled = true; filterContext.Result = new ViewResult() { ViewName = "Error"; }; } 这样,就可以在控制器级别共享异常处理逻辑了。但是,如果想要在多个控制器之间共享异常处理逻辑,就需要使用全局异常处理。

全局级别的异常处理

全局异常处理可以通过在Web.config文件中启用自定义错误来实现。以下是如何配置的示例: <customerrors mode="On" /> 配置完成后,当应用程序发生错误时,会自动显示错误视图。但是,还没有指定错误页面(视图)的名称,这是为什么呢?

FilterConfig类的作用

FilterConfig类负责注册全局过滤器。以下是如何实现的示例: public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); } } HandleErrorAttribute被添加到全局过滤器集合中。这个方法在Global.asax文件的Application_Start事件中被调用。它的作用是处理所有控制器中所有动作方法抛出的异常,并返回共享文件夹中的错误视图。

在控制器级别使用HandleError

如果希望在控制器级别使用HandleErrorAttribute,可以按照以下方式操作: [HandleError] public class TestingController : Controller { // 控制器中的动作方法 } 这样,TestingController中所有动作方法抛出的异常都会被处理。其他未处理的异常将被视为未处理异常。

在动作方法级别使用HandleError

如果希望在动作方法级别使用HandleErrorAttribute,可以按照以下方式操作: public class TestingController : Controller { [HandleError] public ActionResult TestMethod() { // 动作方法的业务逻辑 } } 这样,TestMethod方法抛出的异常将被处理。

在错误视图中显示错误详情

为了在错误视图中显示错误详情,可以将错误视图设置为System.Web.Mvc.HandleErrorInfo模型的强类型视图。然后,可以使用@Model关键字访问成员。其中一个成员是Exception对象。

为不同类型的异常显示不同的视图

可以使用HandleErrorAttribute构造函数的重载版本来为不同类型的异常显示不同的视图。以下是如何实现的示例: [HandleError(ExceptionType = typeof(ArgumentException), View = "ArgumentExceptionView")] public ActionResult TestMethod() { // 动作方法的业务逻辑 } 这样,当TestMethod方法抛出ArgumentException类型的异常时,将显示ArgumentExceptionView视图。

HandleErrorAttribute的局限性

HandleErrorAttribute有一些局限性,例如: 1. 错误不会被记录到任何地方。 2. 控制器外部抛出的异常不会被处理。例如,由于无效的URL导致的异常不会被处理。 3. 不能根据场景进行异常处理。例如,不能为Ajax请求和普通请求提供不同的错误页面。

扩展HandleErrorAttribute

可以通过扩展默认的HandleErrorAttribute来克服上述一些局限性。以下是如何实现的示例: private bool IsAjax(ExceptionContext filterContext) { return filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest"; } public override void OnException(ExceptionContext filterContext) { if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled) { return; } if (IsAjax(filterContext)) { filterContext.Result = new JsonResult() { Data = filterContext.Exception.Message, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; filterContext.ExceptionHandled = true; filterContext.HttpContext.Response.Clear(); } else { base.OnException(filterContext); } // 在这里编写错误记录代码 } 通过扩展HandleErrorAttribute,现在可以记录错误,并且对异常处理有更多的控制。现在可以检查请求是Ajax请求还是普通请求,并相应地进行处理。

处理“资源未找到”异常

“资源未找到”异常既不能被HandleErrorAttribute处理,也不能被CustomHandleErrorAttribute处理。但是,可以使用传统的Web.config方法来处理这种异常。以下是如何配置的示例: <customerrors mode="On"> <error statuscode="404" redirect="~/Testing/NoPageFound" /> </customerrors>

Application_Error是一个应用程序级别的事件,在global.asax文件中定义。每当应用程序中出现未处理的异常时,它都会被执行。既然如此,为什么不总是使用Application_Error呢?

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485