ASP.NET没有魔法——ASP.NET MVC 过滤器(Filter)
2017-11-17 11:47
411 查看
上一篇文章介绍了使用Authorize特性实现了ASP.NET MVC中针对Controller或者Action的授权功能,实际上这个特性是MVC功能的一部分,被称为过滤器(Filter),它是一种面向切面编程(AOP)的实现,本章将从以下几个方面来介绍ASP.NET MVC中的过滤器。
● ASP.NET MVC 中的过滤器及其类型
● ASP.NET MVC 中常用的过滤器
● ASP.NET MVC 过滤器的应用方法
● ASP.NET MVC Action方法的调用与Filter的执行
● ASP.NET MVC 过滤器的创建与获取
● ASP.NET MVC Action及Result过滤器的管道执行
ASP.NET MVC中把过滤器分为以下几类,每一类都是通过一个对应的接口定义的:
● 身份验证过滤器(IAuthenticationFilter):这个过滤器是在MVC5中加入的,它是所有过滤器中优先级最高的,使用身份验证过滤器可以为Action、Controller或者所有的Controller添加身份验证逻辑。身份验证过滤器的核心在于根据请求信息创建一个Principal对象(注:使用Identity的身份验证功能实际上也是创建一个Principal对象),以下是IAuthenticationFilter的定义:
View Code
通过对上面代码的分析得出以下几个结论:
1. 通过Controller上下文及Action的信息找到真实的Action方法后,获取所有过滤器。
2. 先执行身份验证过滤器。
3. 通过身份验证过滤器后执行授权过滤器。
4. 授权过滤器通过后,执行Action过滤器及Action方法。
5. 执行Result过滤器及Result。
● 过滤器提供器(FilterProvider):ASP.NET MVC中有一个过滤器提供器的概念和实际对象,它有三种实现分别对应上述的三种应用方式:
○ GlobalFilterCollection:用于保存全局过滤器实例,可以直接通过它添加和获取过滤器实例,通过它创建的过滤器的Scope为Gobal,创建时可以通过Order参数来决定全局过滤器的执行顺序:
○ FilterAttributeFilterProvider:过滤器特性提供器,通过查找Controller以及Action上的特性来创建过滤器,根据特性标记位置将Scope分为Controller以及Action,在应用特性时可以设置特性的Order属性来决定过滤器的执行顺序:
○ ControllerInstanceFilterProvider:控制器实例过滤器提供器,它用于获取当前Controller实例的过滤器,并且过滤器的Scope为First:
● 过滤器提供器集合(FilterProviderCollection):它包含了上述的所有过滤器提供器,ActionInvoker就是通过它来获取所有相关过滤器的:
FitlerProviderCollection获取过滤器时通过以上三种提供器获取所有相关的过滤器并根据Scope以及Order对过滤器进行排序,以决定过滤器执行顺序。
参考:
https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/controllers-and-routing/understanding-action-filters-cs
http://blog.gauffin.org/2012/06/how-to-handle-transactions-in-asp-net-mvc3/
本文链接:http://www.cnblogs.com/selimsong/p/7839459.html
ASP.NET没有魔法——目录
● ASP.NET MVC 中的过滤器及其类型
● ASP.NET MVC 中常用的过滤器
● ASP.NET MVC 过滤器的应用方法
● ASP.NET MVC Action方法的调用与Filter的执行
● ASP.NET MVC 过滤器的创建与获取
● ASP.NET MVC Action及Result过滤器的管道执行
ASP.NET MVC中的过滤器及其类型
在之前的Entity Framework文章中介绍了EF自带的拦截器(interceptors)功能,ASP.NET MVC中的过滤器也和拦截器一样是一种面向切面(AOP)的编程方式,是一种不修改源代码的前提下对应用程序进行拓展的编程方式。一般AOP用来处理日志记录、性能统计、安全控制、事务处理、异常处理等不会对原有业务数据进行修改的功能。ASP.NET MVC中把过滤器分为以下几类,每一类都是通过一个对应的接口定义的:
● 身份验证过滤器(IAuthenticationFilter):这个过滤器是在MVC5中加入的,它是所有过滤器中优先级最高的,使用身份验证过滤器可以为Action、Controller或者所有的Controller添加身份验证逻辑。身份验证过滤器的核心在于根据请求信息创建一个Principal对象(注:使用Identity的身份验证功能实际上也是创建一个Principal对象),以下是IAuthenticationFilter的定义:
/// <summary>Invokes the specified action by using the specified controller context.</summary> /// <returns>The result of executing the action.</returns> /// <param name="controllerContext">The controller context.</param> /// <param name="actionName">The name of the action to invoke.</param> /// <exception cref="T:System.ArgumentNullException">The <paramref name="controllerContext" /> parameter is null.</exception> /// <exception cref="T:System.ArgumentException">The <paramref name="actionName" /> parameter is null or empty.</exception> /// <exception cref="T:System.Threading.ThreadAbortException">The thread was aborted during invocation of the action.</exception> /// <exception cref="T:System.Exception">An unspecified error occurred during invocation of the action.</exception> public virtual bool InvokeAction(ControllerContext controllerContext, string actionName) { if (controllerContext == null) { throw new ArgumentNullException("controllerContext"); } if (string.IsNullOrEmpty(actionName) && !controllerContext.RouteData.HasDirectRouteMatch()) { throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName"); } ControllerDescriptor controllerDescriptor = this.GetControllerDescriptor(controllerContext); ActionDescriptor actionDescriptor = this.FindAction(controllerContext, controllerDescriptor, actionName);//根据Controller信息及Action名称获取Action的描述信息 if (actionDescriptor != null) { FilterInfo filters = this.GetFilters(controllerContext, actionDescriptor);//获取所有过滤器 try { AuthenticationContext authenticationContext = this.InvokeAuthenticationFilters(controllerContext, filters.AuthenticationFilters, actionDescriptor);//调用身份验证过滤器 if (authenticationContext.Result != null) { AuthenticationChallengeContext authenticationChallengeContext = this.InvokeAuthenticationFiltersChallenge(controllerContext, filters.AuthenticationFilters, actionDescriptor, authenticationContext.Result); this.InvokeActionResult(controllerContext, authenticationChallengeContext.Result ?? authenticationContext.Result); } else { AuthorizationContext authorizationContext = this.InvokeAuthorizationFilters(controllerContext, filters.AuthorizationFilters, actionDescriptor);//调用授权过滤器 if (authorizationContext.Result != null) { AuthenticationChallengeContext authenticationChallengeContext2 = this.InvokeAuthenticationFiltersChallenge(controllerContext, filters.AuthenticationFilters, actionDescriptor, authorizationContext.Result); this.InvokeActionResult(controllerContext, authenticationChallengeContext2.Result ?? authorizationContext.Result); } else { if (controllerContext.Controller.ValidateRequest)//判断是否需要验证请求,使用ValidateInput特性并设置EnableValidation为False时跳过验证 { ControllerActionInvoker.ValidateRequest(controllerContext); } IDictionary<string, object> parameterValues = this.GetParameterValues(controllerContext, actionDescriptor); ActionExecutedContext actionExecutedContext = this.InvokeActionMethodWithFilters(controllerContext, filters.ActionFilters, actionDescriptor, parameterValues);//执行Action过滤器和Action方法 AuthenticationChallengeContext authenticationChallengeContext3 = this.InvokeAuthenticationFiltersChallenge(controllerContext, filters.AuthenticationFilters, actionDescriptor, actionExecutedContext.Result); this.InvokeActionResultWithFilters(controllerContext, filters.ResultFilters, authenticationChallengeContext3.Result ?? actionExecutedContext.Result);//执行Result过滤器及Result } } } catch (ThreadAbortException) { throw; } catch (Exception exception) { ExceptionContext exceptionContext = this.InvokeExceptionFilters(controllerContext, filters.ExceptionFilters, exception);//当捕获异常时执行异常过滤器 if (!exceptionContext.ExceptionHandled)//如果异常过滤器并没有对异常进行处理则继续抛出异常 { throw; } this.InvokeActionResult(controllerContext, exceptionContext.Result); } return true; } return false; }
View Code
通过对上面代码的分析得出以下几个结论:
1. 通过Controller上下文及Action的信息找到真实的Action方法后,获取所有过滤器。
2. 先执行身份验证过滤器。
3. 通过身份验证过滤器后执行授权过滤器。
4. 授权过滤器通过后,执行Action过滤器及Action方法。
5. 执行Result过滤器及Result。
ASP.NET MVC 过滤器的创建与获取
根据上面的介绍知道了可以通过全局过滤器、特性标记以及重载Controller过滤器方法这三种方式来应用过滤器的,那么在执行过程中是如何通过ActionInvoker的GetFilters方法创建和获取它们的呢?● 过滤器提供器(FilterProvider):ASP.NET MVC中有一个过滤器提供器的概念和实际对象,它有三种实现分别对应上述的三种应用方式:
○ GlobalFilterCollection:用于保存全局过滤器实例,可以直接通过它添加和获取过滤器实例,通过它创建的过滤器的Scope为Gobal,创建时可以通过Order参数来决定全局过滤器的执行顺序:
○ FilterAttributeFilterProvider:过滤器特性提供器,通过查找Controller以及Action上的特性来创建过滤器,根据特性标记位置将Scope分为Controller以及Action,在应用特性时可以设置特性的Order属性来决定过滤器的执行顺序:
○ ControllerInstanceFilterProvider:控制器实例过滤器提供器,它用于获取当前Controller实例的过滤器,并且过滤器的Scope为First:
● 过滤器提供器集合(FilterProviderCollection):它包含了上述的所有过滤器提供器,ActionInvoker就是通过它来获取所有相关过滤器的:
FitlerProviderCollection获取过滤器时通过以上三种提供器获取所有相关的过滤器并根据Scope以及Order对过滤器进行排序,以决定过滤器执行顺序。
ASP.NET MVC Action及Result过滤器的管道执行
在Action和Result过滤器的定义中都有两个方法,分别是OnXXXExecuting以及OnXXXExecuted,它们对应Action或者Reuslt执行前和执行后。当一个Action上存在多个Action或者Result过滤器时就会形成一个过滤器管道,其执行方式如下图所示:小结
本文除了介绍ASP.NET MVC的过滤器功能及常用的过滤器外,还通过代码的形式分析了它创建与执行的过程。在一般的项目中使用ASP.NET MVC自带的过滤器就可以满足需求,如授权、错误处理等,但过滤器作为ASP.NET MVC中的一种重要的AOP拓展方式,合理的运用过滤器可以实现,如日志记录、性能分析、Action的事务执行(http://blog.gauffin.org/2012/06/how-to-handle-transactions-in-asp-net-mvc3/,这篇文章就利用Action过滤器实现了数据库的事务)等等功能,并且可以灵活的在不影响原有代码逻辑的情况下对系统进行拓展。参考:
https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/controllers-and-routing/understanding-action-filters-cs
http://blog.gauffin.org/2012/06/how-to-handle-transactions-in-asp-net-mvc3/
本文链接:http://www.cnblogs.com/selimsong/p/7839459.html
ASP.NET没有魔法——目录
相关文章推荐
- ASP.NET没有魔法——ASP.NET MVC 过滤器(Filter)
- ASP.NET MVC Filter (过滤器)的执行顺序
- ASP.NET没有魔法——ASP.NET MVC是如何运行的?它的生命周期是什么?
- ASP.NET没有魔法——ASP.NET MVC 与数据库之Entity Framework Migrations
- ASP.NET MVC 四 过滤器Filter
- ASP.NET没有魔法_ASP.NET MVC 模型验证方法
- ASP.NET MVC 重点教程一周年版 第六回 过滤器Filter
- ASP.NET没有魔法——ASP.NET MVC 与数据库之EF实体类与数据库结构
- ASP.NET MVC 重点教程一周年版 第六回 过滤器Filter
- ASP.NET MVC 第六回 过滤器Filter
- [转]ASP.NET MVC 过滤器Filter
- ASP.NET MVC 重点教程一周年版 第六回 过滤器Filter
- ASP.NET MVC 重点教程一周年版 第六回 过滤器Filter
- ASP.NET没有魔法——ASP.NET MVC & 分层 代码篇
- ASP.NET没有魔法——ASP.NET MVC使用Oauth2.0实现身份验证
- ASP.NET MVC 过滤器Filter
- ASP.NET没有魔法——ASP.NET MVC 模型绑定
- asp.net MVC之 自定义过滤器(Filter) - shuaixf
- ASP.NET没有魔法——ASP.NET MVC使用Area开发一个管理模块
- 【翻译】ASP.NET MVC中实现一个错误处理过滤器[Implementing an Error-Handling Filter]