博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Action Filtering in ASP.NET MVC Applications
阅读量:4935 次
发布时间:2019-06-11

本文共 6671 字,大约阅读时间需要 22 分钟。

Base Interview

MVC中一个重要的功能——Filter,我们通过研究源代码来了解Filter的原理,以及AOP 模式和各种Filter的执行。最重要的是大家通过理解Filter的代码,明白Filter的机制,从而对Filter有一个灵活的运用。

比如你在Action上使用的每一个 [Attribute]大都是Filter,mvc提供四种类型的 Filter:IActionFilter,IAuthorizationFilter,IExceptionFilter,IResultFilter,这四种Filter足以我们所要实现的功能了,还提供了几个现成的可以使用的Filter:OutputCacheAttribute、 HandleErrorAttribute、AuthorizeAttribute。我们知道Filter是横切在Action上的,所以每次执行一个 Action,就会牵扯到这个Action的执行,不同类型的Filter提供不同类型的操作,Filter的设计就是一种AOP设计模式,所以这种方式十分灵活。

介绍如何使用 Authorize 特性控制对操作方法的访问。
介绍如何使用 OutputCache 特性缓存操作方法的输出结果。
解释如何向 MVC 应用程序添加自定义操作筛选器。

对于四种类型的Filter,各自有不同的方法,并以此来实现不同的功能,我们可以发挥自己的创造力,定制一个自己的Filter,来完成自己想要的功能。一般的Filter应用的场景有:缓存、验证、异常,以及处理Action上下文等,要想实现自己的Filter 只要继承相应的接口并重写接口的方法就可以了。

  • 授权筛选器,用于做出关于是否执行操作方法(如执行身份验证或验证请求的属性)的安全决策。 类是授权筛选器的一个示例。
  • 操作筛选器,用于包装操作方法的执行操作。此筛选器可以执行其他处理,如向操作方法提供额外数据、检查返回值或取消执行操作方法。
  • 结果筛选器,用于包装 对象的执行操作。此筛选器可以对结果执行其他处理,如修改 HTTP 响应。 类是结果筛选器的一个示例。
  • 异常筛选器,如果在操作方法中某处引发了未经处理的异常,则从授权筛选器开始执行,执行结果筛选器后结束。异常筛选器可用于执行诸如日志记录或显示错误页之类的任务。 类是异常筛选器的一个示例

Why Use Filter

我们知道Filter是一种AOP模式,也就是说它提供我们可以对一系列操作进行横切干扰的手段,而且它解耦了依赖关系。想想这么一种场景,在传统的WebForm中,某一个页面的访问必须去验证当前用户是否符合某一个要求,比如已登录,这时,我们需要获取请求的上下文,分析当前用户的行为状态,从而得到这个条件是否成立,如果我们有很多这种页面,比如所有的后台管理页面需要管理员的登录,我们是不是每一页都写一个这样的验证呢?我们当然不会这么蠢,我们会聪明的把验证的逻辑封装成一个验证类,然后从各个页面调用验证类的验证逻辑,从而得知当前用户是否通过验证。
这样还是不够好,因为我们不得不在每一处反复写我们的调用验证类的验证代码,显然这些工作是重复的,因为那个时候还没有AOP的概念,所以我们不得不多付出点代价。
现在有了mvc,它理所应当为我们提供一个AOP的框架,而Filter就是这么一种模式,它的出现容许我们以一种更为简单的方式来实现类似的功能,在使用的时候我们只需要像该某个商品贴标签式的方式给Action“贴”上一个Attribute就行了,一切搞定,没有一点多于的代码。

Use default Filter

操作筛选器的某些可能用途包括:

  • 日志记录,目的是跟踪用户交互。
  • “反图像攫取”,用于防止在自己网站之外的网页中加载图像。
  • 爬网程序筛选,用于根据浏览器用户代理来更改应用程序行为。
  • 本地化,用于设定区域设置。
  • 动态操作,用于将操作注入到控制器中。

操作筛选器是以从 ActionFilterAttribute 中继承的特性类的形式实现的。 ActionFilterAttribute 是一个具有以下四个可以重写的虚拟方法的抽象类:OnActionExecuting、OnActionExecuted、OnResultExecuting 和 OnResultExecuted。若要实现操作筛选器,您至少必须重写这些方法之一。

ASP.NET MVC 框架将先调用操作筛选器的 OnActionExecuting 方法,然后再调用以操作筛选器特性标记的任意操作方法。同样,该框架将在操作方法完成后调用 OnActionExecuted 方法。

调用 OnResultExecuting 方法后,要立即调用您的操作返回的 ActionResult 实例。执行结果后,紧接着就要调用 OnResultExecuted 方法。这些方法对于执行日志记录、缓存输出结果之类的操作非常有用。

下面演示自带的Filter 如 类

配置缓存文件如下

标记制作器中的Action

[OutputCache(CacheProfile = "MyProfile", Duration = 10)]public ActionResult About(){    ViewData["Message"] = "This page was cached at " + DateTime.Now;    return View();}

Creating a custom action filter

下面的示例演示一个简单的操作筛选器,该操作筛选器记录调用操作方法之前和之后的跟踪消息

注意: 按照约定,操作筛选器特性的名称应以“Attribute”作为结尾,LogFilterAttribute 或 OutputFilterAttribute。如创建一个日志异常的Filter

public class LoggingFilterAttribute : ActionFilterAttribute{    public override void OnActionExecuting(ActionExecutingContext filterContext)    {        filterContext.HttpContext.Trace.Write("(Logging Filter)Action Executing: " +            filterContext.ActionDescriptor.ActionName);        base.OnActionExecuting(filterContext);    }    public override void OnActionExecuted(ActionExecutedContext filterContext)    {        if (filterContext.Exception != null)            filterContext.HttpContext.Trace.Write("(Logging Filter)Exception thrown");        base.OnActionExecuted(filterContext);    }}

使用也很简单 ,用操作筛选器特性标记的操作方法的控制器

[LoggingFilter]        public ActionResult Index()        {            ViewBag.Message = "修改此模板以快速启动你的 ASP.NET MVC 应用程序。";            return View();        }        [LoggingFilter]        public ActionResult About()        {            ViewBag.Message = "你的应用程序说明页。";            return View();        }

或者在控制器中重写

protected override void OnActionExecuting(ActionExecutingContext filterContext)        {            filterContext.HttpContext.Trace.Write("(Controller)Action Executing: " +                filterContext.ActionDescriptor.ActionName);            base.OnActionExecuting(filterContext);        }        [NonAction]        protected override void OnActionExecuted(ActionExecutedContext filterContext)        {            if (filterContext.Exception != null)                filterContext.HttpContext.Trace.Write("(Controller)Exception thrown");            base.OnActionExecuted(filterContext);        }        [LoggingFilter]        public ActionResult Index()        {            ViewBag.Message = "修改此模板以快速启动你的 ASP.NET MVC 应用程序。";            return View();        }        [LoggingFilter]        public ActionResult About()        {            ViewBag.Message = "你的应用程序说明页。";            return View();        }

或者注册全局的Filter,在App_Start 中的 FilterConfig.cs文件中(MVC4)注册我们的LoggingFilterAttribute

public static void RegisterGlobalFilters(GlobalFilterCollection filters)        {            filters.Add(new LoggingFilterAttribute());            filters.Add(new HandleErrorAttribute());        }

我们也可以看下HandleErrorAttribute类 F12

// 摘要:    //     表示一个特性,该特性用于处理由操作方法引发的异常。    [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);    }

如我看可以看到 Master的额外参数,我们可以在控制器中如下标记

[HandleErrorAttribute(Master="我是参数 但不是模板页")]        public ActionResult Contact()        {            ViewBag.Message = "你的联系方式页。";            return View();        }

我们也可以添加我们想要的值,如添加一个属性在 (public string Message { get; set; } )在LoggingFilterAttribute 类

我们也可以把该filter特性标记上面的方法中,如:

[LoggingFilterAttribute (Message = "action")]public class IndexController : Controller{…}

全局中我们可以通过下面方式获取控制器与action的名称

filterContext.RouteData.GetRequiredString("Controller") + filterContext.RouteData.GetRequiredString("action");

Summary

在本篇文章中,讲述的内容非常有限,主要讨论了怎么获取Filter的,以及Controller与各种 Filter的关系,还有Filter的4种类型,但是我们没有具体讨论4种类型Filter的方法。还有最终要的就是大家通过这个探究这个过程,真正了理解Filter的设计思想和AOP在mvc中的运用,以及Filter的功能强大之处。

Link:

转载于:https://www.cnblogs.com/Irving/archive/2012/12/11/2812867.html

你可能感兴趣的文章
通过自动回复机器人学Mybatis---加强版
查看>>
点击startup.bat启动tomcat出现乱码
查看>>
BUAA_OO第二单元总结性博客作业——多线程电梯架构
查看>>
C++ 11
查看>>
高级软件工程课程总结
查看>>
MySQL对时间的处理总结
查看>>
笔记四:python乱码深度剖析二
查看>>
《PHP程序员面试笔试宝典》——如何回答技术性的问题?
查看>>
【转载】Amit’s A star Page 中译文
查看>>
GitHub Blog创建以及本地管理
查看>>
注册谷歌账号并验证时显示号码无法用于验证的问题
查看>>
hive基本操作与应用
查看>>
(C#)设计模式之状态模式
查看>>
java反射(2.0)
查看>>
详解C# 网络编程系列:实现类似QQ的即时通信程序
查看>>
Hive 变量和属性
查看>>
验证邮箱合法性的一些测试样例
查看>>
Python安装第三方库 xlrd 和 xlwt 。处理Excel表格
查看>>
课后作业-阅读任务-阅读提问-3
查看>>
Asp.Net Core 中利用QuartzHostedService 实现 Quartz 注入依赖 (DI)
查看>>