Asp.Net MVC Filter 实现方式和作用范围控制
2014-04-10 08:22
344 查看
MVC中的Filte 简单又优雅的实现了AOP ,在日志,权限,缓存和异常处理等方面用的比较多。但本文不是讨论Filter这些功能点,而是总结Filter实现的方式。说实现也不太准确,也就是它的呈现方式。自带有四种Filter(借用了Liam wang的图)
View Code
在Global中加人
这样在方法前面加入[DIMessage] 即可
用的最多的还是继承默认Filter和继承接口实现,他们的作用范围除了可以通过直接“贴”在Action或者Controller上面来控制还可以通过全局注册和Provider的方式来控制。
一、全局注册
在App_Start 文件夹中的FilterConfig已经默认注册了一个全局的 HandleErrorAttribute,这样相当于给所有的方法加上了HandleError标签
二、FilterProvider
但如果我不想全局注册,也不想一个一个去加在方法的上方,我想一次性给所有控制器的Index方法加一个Filter,那怎么办? 用Filter provider 。
从IFilterProvider接口开始
实现了这个接口并注册,在触发一个Action时候,GetFilters就会被调用。
而上文的Filter类是这样的,它包装了filter对象,而真正执行的filter就是这个instance。
Order和Scope定义了这个Filter的优先级和范围。FilterScope是枚举类型,包含First,Global,Controller,Action,Last。
我们先定义一个CustomFilterWrapper ,继承Filter,让其支持lambda 便于选择过滤。
我们再实现一个CustomFilterProvider
这样我们就可以Global中注册了。这样我们可以通过LINQ来选择我们需要加入Filter的方法了。
特此分享,希望对你有帮助,Thanks!
参考:Pro Asp.Net MVC3 FrameWork
public class NinjectDependencyResolver : IDependencyResolver { private readonly IKernel _kernel; public NinjectDependencyResolver() { _kernel = new StandardKernel(); AddBindings(); } public object GetService(Type serviceType) { return _kernel.TryGet(serviceType); } public IEnumerable<object> GetServices(Type serviceType) { return _kernel.GetAll(serviceType); } public IBindingToSyntax<T> Bind<T>() { return _kernel.Bind<T>(); } public IKernel Kernel { get { return _kernel; } } private void AddBindings() { _kernel.Bind<IUserRepository>().To<UserRepository>(); _kernel.Bind<IDownloadFileRepository>().To<DownloadRepository>(); _kernel.Bind<IAuthProvider>().To<FormsAuthProvider>(); //绑定 Bind<IMessageProvider>().To<SimpleMessageProvider>(); } }
View Code
在Global中加人
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); DependencyResolver.SetResolver(new NinjectDependencyResolver()); FilterProviders.Providers.Insert(0,new DIFilterProvider()); //插在第一个。(这样便于实现需要IOC的Filter,不然其他的Provider找到Filter就返回了) RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); }
这样在方法前面加入[DIMessage] 即可
用的最多的还是继承默认Filter和继承接口实现,他们的作用范围除了可以通过直接“贴”在Action或者Controller上面来控制还可以通过全局注册和Provider的方式来控制。
一、全局注册
在App_Start 文件夹中的FilterConfig已经默认注册了一个全局的 HandleErrorAttribute,这样相当于给所有的方法加上了HandleError标签
public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute() { ExceptionType = typeof(NullReferenceException),//可以设置捕获的异常类型 View = "SpecialError"//默认跳转的视图 }); } }
二、FilterProvider
但如果我不想全局注册,也不想一个一个去加在方法的上方,我想一次性给所有控制器的Index方法加一个Filter,那怎么办? 用Filter provider 。
从IFilterProvider接口开始
public interface IFilterProvider { IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor); }
实现了这个接口并注册,在触发一个Action时候,GetFilters就会被调用。
而上文的Filter类是这样的,它包装了filter对象,而真正执行的filter就是这个instance。
namespace System.Web.Mvc {public class Filter { public const int DefaultOrder = -1; public Filter(object instance, FilterScope scope, int? order) { // ...statements removed for clarity... } public object Instance { get; protected set; } public FilterScope Scope { get; protected set;} public int Order { get; protected set; } } }
Order和Scope定义了这个Filter的优先级和范围。FilterScope是枚举类型,包含First,Global,Controller,Action,Last。
我们先定义一个CustomFilterWrapper ,继承Filter,让其支持lambda 便于选择过滤。
public class CustomFilterWrapper : Filter { public CustomFilterWrapper(object instance, FilterScope scope, int? order,Func<ControllerContext,ActionDescriptor,bool> selector ) : base(instance, scope, order) { Selector = selector; } public Func<ControllerContext, ActionDescriptor, bool> Selector//便于通过控制器名称和action名称来过滤 { get; set; } }
我们再实现一个CustomFilterProvider
public class CustomFilterProvider : IFilterProvider { private IList<CustomFilterWrapper> wrappers; public CustomFilterProvider() { wrappers = new List<CustomFilterWrapper>(); } public IList<CustomFilterWrapper> Wrappers { get { return wrappers; } } public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor) { return wrappers.Where(e => e.Selector(controllerContext, actionDescriptor)); } }
这样我们就可以Global中注册了。这样我们可以通过LINQ来选择我们需要加入Filter的方法了。
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); CustomFilterProvider customFilterProvider = new CustomFilterProvider(); customFilterProvider.Wrappers.Add(new CustomFilterWrapper(new LogFilterAttribute(), FilterScope.Action, 1, (c, a) => a.ActionName == "Index"));//所有控制器的Action方法会触发Logfilter FilterProviders.Providers.Add(customFilterProvider);
RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); }
特此分享,希望对你有帮助,Thanks!
参考:Pro Asp.Net MVC3 FrameWork
相关文章推荐
- ASP.NET MVC 入门10、Action Filter 与 内置的Filter实现(实例-防盗链)
- ASP.NET MVC 中如何实现基于角色的权限控制
- ASP.NET MVC验证 - 使用哪种方式实现客户端服务端双重异步验证
- ASP.NET MVC 入门 -- 10、Action Filter 与 内置的Filter实现(实例-防盗链)
- ASP.NET MVC(模型(Model),视图(View)和控制Controller)实践:实现身份验证权限管理
- 在ASP.NET MVC中实现基于URL的权限控制
- ASP.NET MVC实现POST方式的Redirect
- ASP.NET MVC 中实现基于角色的权限控制的处理方法
- ASP.NET MVC实现Localize站点的Action Filter
- 利用ResultFilter实现asp.net mvc 页面静态化
- ASP.NET MVC中权限控制的简单实现
- ASP.NET MVC 入门9、Action Filter 与 内置的Filter实现(介绍)
- ASP.NET MVC 入门9、Action Filter 与 内置的Filter实现(介绍)
- ASP.NET MVC 入门9、Action Filter 与 内置的Filter实现(介绍)
- 尝试asp.net mvc 基于controller action 方式权限控制方案可行性
- ASP.NET MVC实现权限控制
- ASP.NET MVC 入门10、Action Filter 与 内置的Filter实现(实例-防盗链)
- ASP.NET MVC 入门10、Action Filter 与 内置的Filter实现(实例-防盗链)
- ASP.NET MVC 入门9、Action Filter 与 内置的Filter实现(介绍)
- Asp.net下使用HttpModule模拟Filter,实现权限控制