实现拦截器
在ASP.NET MVC中,有三种拦截器:Action拦截器、Result拦截器和Exception拦截器。其实所谓的ASP.NET MVC拦截器,也没什么神秘的,就是一个普通的类而已。只不过需要继承FilterAttribute基类,Action拦截器还要实现IActionFilter接口,而Exception拦截器需要实现IExceptionFilter接口。
我们先来看实现:让我们在Controllers目录下新建一个Filters目录,然后在Filters下新建两个类,一个叫AccountFilter.cs一个叫ExceptionFilter。首先是AccountFilter.cs的代码。
AccountFilter.cs:
AccountFilter.csusing System.Web.Mvc; namespace MvcWeb.Controllers.Filters { public class AccountFilter : ActionFilterAttribute { //Action 执行前 (未登录通过。跳转到 “~/Account/LoginOn” ) public override void OnActionExecuting(ActionExecutingContext filterContext) { var authenticate = StructureMap.ObjectFactory.GetInstance<Ants.Provider.IAuthenticateProvider>(); if (!authenticate.IsAuthenticated) { filterContext.Result = new RedirectResult("~/Account/LoginOn"); } base.OnActionExecuting(filterContext); } } }
这个地方我得解释一下,你拦截器拦截了Action,在做处理时难免要用到被拦截Action相关的东西,例如在我们的例子中,就需要想被拦截Action所在Controller的ViewData中添加内容,所以,拦截器方法有一个参数表示被拦截Action的上下文是顺理成章的事。
下面再看ExceptionFilter这个拦截器,它是在Action出现异常时发挥作用的。
ExceptionFilter.cs
using System.Web.Mvc; namespace MvcWeb.Controllers.Filters { public class ExceptionFilter : FilterAttribute, IExceptionFilter { void IExceptionFilter.OnException(ExceptionContext filterContext) { filterContext.Controller.ViewData["Error"] = filterContext.Exception; filterContext.Result = new ViewResult() { ViewName = "Error", ViewData = filterContext.Controller.ViewData, }; filterContext.ExceptionHandled = true; } } }
异常拦截器需要继承FilterAttribute,但是不要实现IActionFilter,而是要实现IExceptionFilter接口,这个接口只有一个方法:OnException,顾名思义,当然是发生异常时被调用了。我们看看我让它做了什么:首先将异常信息(ExceptionContext一样也是上下文,而其成员的Exception就是一个Exception类型的实例,就是被抛出的异常)记录到ViewData相应的键值里,然后我们要呈现Error这个视图。
注意!这里已经不是Controller里了,而是另一个类,所以当然不能调用View方法 返回ViewResult实例了。我们只好新建一个ViewResult实例,并将其视图名设为Error,将上下文中的DataView传过去。
最后那行filterContext.ExcepitonHandled = true;很重要,这行的意思是告诉系统,异常已经处理,不要再次处理了。应用了ExceptionFilter的Action中不用再写try…catch语句啦,因为异常拦截器成功拦截了异常,并做了相应处理。
应用拦截器
好了,拦截器建立完了,要怎么应用到相应的Action上呢?在ASP.NET MVC中,应用拦截器简直是轻松加愉快。只要将拦截器当做Attribute写在要应用此拦截器的Action上就行了.比如:
[Filters.AccountFilter] [Filters.ExceptionFilter] public ActionResult Test() { }