在asp.net mvc中除了使用try...catch/finally来处理异常外,它提供了一种通过在Controller或者Action上添加特性的方式来处理异常。
HandleErrorAttribute首先看一下该特性的定义
using System;namespace System.Web.Mvc
{ // 摘要:
// 表示一个特性,该特性用于处理由操作方法引发的异常。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class HandleErrorAttribute : FilterAttribute, IExceptionFilter
{ // 摘要:
// 初始化 System.Web.Mvc.HandleErrorAttribute 类的新实例。
public HandleErrorAttribute(); // 摘要:
// 获取或设置异常的类型。 //
// 返回结果:
// 异常的类型。
public Type ExceptionType { get; set; } //
// 摘要:
// 获取或设置用于显示异常信息的母版视图。 //
// 返回结果:
// 母版视图。
public string Master { get; set; } //
// 摘要:
// 获取此特性的唯一标识符。 //
// 返回结果:
// 此特性的唯一标识符。
public override object TypeId { get; } //
// 摘要:
// 获取或设置用于显示异常信息的页视图。 //
// 返回结果:
// 页视图。
public string View { get; set; } // 摘要:
// 在发生异常时调用。 //
// 参数:
// filterContext: // 操作筛选器上下文。 //
// 异常:
// System.ArgumentNullException: // filterContext 参数为 null。
public virtual void onException(ExceptionContext filterContext);
}
}ExceptionType:属性,相当于try catch(Exception)中的catch捕获的异常类型,默认所有异常类型。
View:异常展示视图,这个视图需要在目录Views/Shared/下。例如:
Order:该属性是父类FilterAttribute的一个属性,用来获取或者设置执行操作筛选器的顺序,默认-1,-1最先执行。
一个例子
在Index中直接抛出一个异常,我们现在需要做的就是通过HandlerError特性捕获到这个异常,并且在视图MyError上显示详细信息。
步骤1:添加特性
public class UserController : Controller
{ // GET: User
[HandleError(ExceptionType = typeof(Exception), View = "MyError")]
public ActionResult Index()
{ throw new Exception("Sorry,threre is an error in your web server.");
}
}步骤2:定义错误视图,并通过@Model获取异常对象并显示错误信息。
@{
Layout = null;
}
@Model.Exception.GetType().Name
@Model.Exception.Message
@Model.ControllerName
@Model.ActionName
@Model.Exception.StackTrace
步骤3:注册过滤器。
在App_Start目录添加类FilterConfig
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}在Global.asax中注册
public class MvcApplication : System.Web.HttpApplication
{ protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
GlobalConfiguration.Configure(WebApiConfig.Register);
}
}步骤4:开启自定义错误配置
...
测试
以上是采用ErrorHanlder的默认实现的方式,当然我们也可以自定义异常处理过滤器,方法很简单继承HandleErrorAttribute类,并且重写OnException方法即可。
////// 自定义异常过滤器 /// public class CustomerErrorAttribute : HandleErrorAttribute { public override void onException(ExceptionContext filterContext) { //如果没有处理该异常 if (!filterContext.ExceptionHandled) { if (filterContext.Exception.Message.Contains("Sorry,threre is an error in your web server.")) { filterContext.ExceptionHandled = true; filterContext.HttpContext.Response.Write("这是一个自定义异常处理过滤器"); } } } }
public class UserController : Controller
{ // GET: User
[CustomerError(ExceptionType = typeof(Exception), View = "MyError")] public ActionResult Index()
{ throw new Exception("Sorry,threre is an error in your web server.");
}
} public class FilterConfig
{ public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new CustomerErrorAttribute());
}
}测试
好了,自定义的异常处理过滤器已经起作用了。
需要注意在自定义处理异常过滤器的时候需要重写OnException方法,该方法有一个ExceptionContext类型的参数。
// 摘要:
// 提供使用 System.Web.Mvc.HandleErrorAttribute 类的上下文。
public class ExceptionContext : ControllerContext
{ // 摘要:
// 初始化 System.Web.Mvc.ExceptionContext 类的新实例。
public ExceptionContext(); //
// 摘要:
// 使用指定的控制器上下文针对指定的异常初始化 System.Web.Mvc.ExceptionContext 类的新实例。 //
// 参数:
// controllerContext: // 控制器上下文。 //
// exception: // 异常。 //
// 异常:
// System.ArgumentNullException: // exception 参数为 null。
public ExceptionContext(ControllerContext controllerContext, Exception exception); // 摘要:
// 获取或设置异常对象。 //
// 返回结果:
// 异常对象。
public virtual Exception Exception { get; set; } //
// 摘要:
// 获取或设置一个值,该值指示是否已处理异常。 //
// 返回结果:
// 如果已处理异常,则为 true;否则为 false。
public bool ExceptionHandled { get; set; } //
// 摘要:
// 获取或设置操作结果。 //
// 返回结果:
// 操作结果。
public ActionResult Result { get; set; }
}需要注意的是,在自定义的异常过滤器中,如果对异常已经处理了,需要将ExceptionHandled设置为true,这样其它的过滤器可以根据该值判断当前异常是否已经处理过了。
通过异常处理过滤器的特性,你可以更方便的来处理action或者Controller中的异常,比try--catch用起来更方便,用这种方式,也可以简化异常处理的代码,少一些大块儿大块儿的异常处理代码。



