过滤器是
ASP.NET MVC
中很重要的一个功能,过滤器(Filters)的出现使得我们可以在ASP.NET MVC程序里更好的控制浏览器请求过来的URL,不是每个请求都会响应内容,只响应特定内容给那些有特定权限的用户。
过滤器理论上有以下功能:
实现过滤器的两种方法:
注意:如果继承自接口,则需要让类实现FilterAttribute,才能作为特性使用。参数类均继承自ControllerContext,主要包含属性请求上下文,路由数据,结果。
四种常用的过滤器: 过滤器类型 | 接口 | 默认实现 | 描述 :–:|:–:|:–:|:–: Authorization | IAuthorization | AuthorizeAttribute | 首先运行,在其他过滤器的操作方法 Action | IActionFilter | ActionFilterAttribute | 运行之前和之后的动作方法 Result | IResultFilter | ActionFilterAttribute | 运行前后执行的操作结果 Exception | IExceptionFilter | HandleErrorAttribute | 如果只运行一个过滤器,操作方法或行动结果抛出一个异常
MVC5 中新增了 Authentication 过滤器,用于验证。在 MVC5 中,将原本的 Authorization 拆分为 Authentication(身份验证)和 Authorization(授权)两个,MVC 接受到 Web 页面请求时,首先将执行所有的 Authentication 过滤器,如果请求需要认证且已经被验证过了,就会继续下一步处理,若没有通过身份验证,则会停止处理。
下面先说下身份过滤验证器,然后以身份过滤验证器为例介绍几种实现过滤器的方法,再介绍后续的其他的过滤器!
定义身份验证的过滤器,需要在约束的Action执行前来执行,重写OnAuthorization方法。
通过一个简单的实例,来展示Filter的模式:
现在项目中添加一个 Filter 文件夹来存储过滤器,然后来写第一个 Filter 示例 - MyAuthorization.cs
:
using System.Web.Mvc;
namespace STU_mvc.Areas.UserManage.Filters
{
public class MyAuthorization: AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
//.net framework 默认身份验证
//base.OnAuthorization(filterContext);
//跳转页面,使用Result,而不是使用Response.Redirect() 因为它会继续执行Action
//filterContext.Result = new RedirectResult(UrlHelper.GenerateUrl("","","","","","",true));
//获取路由数据,当前上下文匹配到路由规则后,得到的一个对象
//filterContext.RouteData
//获取上下文
filterContext.HttpContext.Response.Write("Test");
}
}
}
注意: 这是一个身份验证的 Filter ,因此这个类必须继承自System.Web.Mvc
中的 AuthorizeAttribute
,并对OnAuthorization()
方法进行重写。
写好了 Filter 还得去调用他,调用 Filter 的方法就是,在 Action 前为其申明一个特性。
using STU_mvc.Areas.UserManage.Filters;
using System.Web.Mvc;
namespace STU_mvc.Areas.UserManage.Controllers
{
public class HomeController : Controller
{
// GET: UserManage/Home
[MyAuthorization]
public ActionResult Index()
{
return View();
}
}
}
如上代码中的控制器直接返回了一个 Test ,编译-运行-访问当前路由,会发现浏览器在 html 代码前直接附加了一个 Test
,由此可知,过滤器发生在 Action 之前。
注意:Filter 是作为特性而附加给 Action 的,因此可以被不同的 Action 重复调用,且只在调用后才会执行。同样,如果一个 Controller 中的所有 Action 都需要使用这个 Filter ,则可以直接给当前 Controller 类附加上这个 Filter 特性即可。
Global.asxs 中 FilterConfig 调用了 App_Start
中的 FilterConfig.cs
文件,这个文件在全局中申明了过滤器,及所有在此处注册的过滤器,会被所有 Controller 的 所有 Action 执行。
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//filters.Add(new HandleErrorAttribute());
//在全局中注册过滤器,则所有控制器的所有行为都会执行
filters.Add(new MyAuthorization());
}
}
RegisterGlobalFilters()
方法的形参表面,filters 是一个集合,因此只需要在其中使用 filters 的 Add 方法申明过滤器即可。
针对某一控制器进行重写,应用范围为当前控制器下的所有的行为。
在控制器中 输入 override OnAuthentication
自动补全,为当前控制器重写该方法:
protected override void OnAuthentication(AuthenticationContext filterContext)
{
filterContext.HttpContext.Response.Write("test for controller");
}
重写完成后,调试可以发现, 被重写OnAuthentication
的 home
控制器执行了 filter 的内容,而未被重写的test
控制器则不受影响。
同样的,也可以添加一个继承自
Controller
的基类,并重写基类的OnAuthentication
,之后让控制器不再继承Controller
,而是间接继承基类。 即: HomeController -> BaseController -> Controller ,通过为 BaseController 重写 filter 来实现过滤器。
异常处理过滤器,用于当发生异常时,进行自定义异步处理,记录日志,跳转页面等。
首先创建过滤器 MyException.cs
,同样的,在 Filter 文件夹下新建一个类,继承自 HandleErrorAttribute
注意:OnException 的 base 特性不能删除,否则捕获不到异常
namespace STU_mvc.Areas.UserManage.Filters
{
public class MyExcepition: HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
//OnException 的 base 特性不能删除,否则捕获不到异常
base.OnException(filterContext);
//记录日志
//直接跳转到异常处理页面
filterContext.Result= new RedirectResult("/Error/400.html");
}
}
}
然后使用全局注册,通常来说,异常处理都是全局有效的:
注意:如果要实现自定义
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//系统默认的异常处理过滤器
//filters.Add(new HandleErrorAttribute());
//在全局中注册过滤器,则所有控制器的所有行为都会执行
//filters.Add(new MyAuthorization());
//添加自己的异常处理过滤器
filters.Add(new MyExcepition());
}
}
注意: 要使用自定义的异常处理,需要在
web.config
中为system.web
添加<customErrors mode ="on" />
节点,开启自定义异常。
<system.web>
<customErrors mode ="On" defaultRedirect="Error/400.html"/>
……
配置完成后,我们随便输入一个不匹配的路由,就会返回到我们提前编写好的400页面,并通过 url 暴露出异常的路由信息,而正常的路由请求则不受此影响。
##行为过滤器
Action 过滤器继承ActionFilterAttribute
实现,并提供了在两个不同时间点执行代码的能力,分别在 行为执行前(OnActionExecuting)/行为执行后(OnActionExecuted) 执行相关操作。
Filter 目录下新建一个类MyAction
,并继承ActionFilterAttribute
public class MyAction: ActionFilterAttribute
{
//行为执行前
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write("This line is Before Action execute!");
//base.OnActionExecuting(filterContext);
}
//行为执行后,结果输出前
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write("This line is After Action execute!");
//base.OnActionExecuted(filterContext);
}
}
同样的,添加特性使其生效
public class HomeController : Controller
{
// GET: UserManage/Home
[MyAction]
public ActionResult Index()
{
Response.Write("Action Execut");
return View();
}
}
效果如下:
return 的 view() 是在 Action 完成后执行的,所以会先显示两个 filter 的结果,再返回 view(),而 Action 中的内容则在二者之间显示。
同样继承自ActionFilterAttribute
实现,并提供了在两个不同时间点执行代码的能力,分别在 结果执行前(On ResultExecuting)/结果执行后(OnResultExecuted) 执行相关操作。
首先创建过滤器 MyResult.cs
,同样的,在 Filter 文件夹下新建一个类,继承自 ActionFilterAttribute
public class MyResult: ActionFilterAttribute
{
//结果执行前执行
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.HttpContext.Response.Write("Before Result<bt />");
}
//结果执行后执行
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.HttpContext.Response.Write("After Result<bt />");
}
}
同样的,添加特性使其生效
public class HomeController : Controller
{
// GET: UserManage/Home
[MyResult]
public ActionResult Index()
{
Response.Write("Action Execut");
return View();
}
}
效果如下:
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有