分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 代码编程

MVC四大筛选器—ActionFilter&ResultedFilter

发布时间:2023-09-06 01:48责任编辑:胡小海关键词:MVC

AuthorizeFilter筛选器

在Action的执行中包括两个重要的部分,一个是Action方法本身逻辑代码的执行,第二个就是Action方法的筛选器的执行。

MVC4中筛选器都是以AOP(面向方面编程)的方式来设计的,通过对Action方法上标注相应的Attribute标签来实现。MVC4提供了四种筛选器,分别为:AuthorizationFilter、ActionFilter、ExceptionFilter和ResultFilter,他们分别对应了四个筛选器接口IAuthorizationFilter、IActionFilter、IExceptionFilter和IResultFilter。

这四种筛选器都有派生于一个公共的类FilterAttribute,该类指定了筛选器的执行顺序Order和是否允许多个应用AllowedMultiple。这四种筛选器默认的执行顺序为最先进行授权筛选,最后进行异常处理,中间则是ActionFilter和ResultedFilter。

下面是抽象类FilterAttribute的类图

下面我们来具体列举一下各个筛选器的作用和实现

从字面上我们就能看出这是对Controller或Action方法授权的筛选器,即在Controller或Action方法执行前,首先会先执行该筛选器,若通过,才会继续执行。下面是此筛选器的简单类图

AuthorizeAttribute为最终授权筛选器的实现者,它实现了IAuthorizationFilter接口和FilterAttribute抽象类,接口中的OnAuthorization(AuthorizationContext filterContext)方法是最终验证授权的逻辑(其中AuthorizationContext是继承了ControllerContext类)

[csharp]view plaincopy
  1. protectedvirtualboolAuthorizeCore(HttpContextBasehttpContext)
  2. {
  3. if(httpContext==null)
  4. {
  5. thrownewArgumentNullException("httpContext");
  6. }
  7. IPrincipaluser=httpContext.User;
  8. if(!user.Identity.IsAuthenticated)
  9. {
  10. returnfalse;
  11. }
  12. if(_usersSplit.Length>0&&!_usersSplit.Contains(user.Identity.Name,StringComparer.OrdinalIgnoreCase))
  13. {
  14. returnfalse;
  15. }
  16. if(_rolesSplit.Length>0&&!_rolesSplit.Any(user.IsInRole))
  17. {
  18. returnfalse;
  19. }
  20. returntrue;
  21. }

AuthorizeCore方法是最终OnAuthorization()方法调用的最终逻辑,从代码可以看出,当同时指定了users和roles时,两者只有同时满足条件时才可以验证授权通过。如

[csharp]view plaincopy
  1. [Authorize(Users="zhangsan",Roles="Admin")]
  2. publicActionResultActionMethod()
  3. {
  4. }

则只有用户zhangsan,且用户属于Admin角色时才能验证授权通过。

若验证不通过时,OnAuthorization方法内部会调用HandleUnauthorizedRequest

虚方法进行处理,代码如下:

[csharp]view plaincopy
  1. protectedvirtualvoidHandleUnauthorizedRequest(AuthorizationContextfilterContext)
  2. {
  3. //ReturnsHTTP401-seecommentinHttpUnauthorizedResult.cs.
  4. filterContext.Result=newHttpUnauthorizedResult();
  5. }

该方法设置了参数上下文中ActionResult的值,用于供View展示。

我们可以自定义Authorize筛选器,由于OnAthurization()、AuthorizeCore()和HandleUnauthorizedRequest()方法都是虚方法,我们自定义的Authorize筛选器只需要继承AuthorizeAttribute类,重写以上三种方法,这样就可以自定义自己的验证规则和验证失败时的处理逻辑了。

IAuthorizationFilter还有其他类型的实现类,如RequireHttpsAttribute、ValidateInputAttribute都是实现了OnAuthorization()方法,来完成各自筛选器处理的。

ExceptionFilter过滤器


该筛选器是在系统出现异常时触发,可以对抛出的异常进行处理。所有的ExceptionFilter筛选器都是实现自IExceptionFilter接口

[csharp]view plaincopy
  1. publicinterfaceIExceptionFilter
  2. {
  3. voidOnException(ExceptionContextfilterContext);
  4. }

实现OnException方法来实现对异常的自定义处理

MVC4中实现了默认的异常处理机制,源码如下

[csharp]view plaincopy
  1. publicvirtualvoidOnException(ExceptionContextfilterContext)
  2. {
  3. if(filterContext==null)
  4. {
  5. thrownewArgumentNullException("filterContext");
  6. }
  7. if(filterContext.IsChildAction)
  8. {
  9. return;
  10. }
  11. //Ifcustomerrorsaredisabled,weneedtoletthenormalASP.NETexceptionhandler
  12. //executesothattheusercanseeusefuldebugginginformation.
  13. if(filterContext.ExceptionHandled||!filterContext.HttpContext.IsCustomErrorEnabled)
  14. {
  15. return;
  16. }
  17. Exceptionexception=filterContext.Exception;
  18. //IfthisisnotanHTTP500(forexample,ifsomebodythrowsanHTTP404fromanactionmethod),
  19. //ignoreit.
  20. if(newHttpException(null,exception).GetHttpCode()!=500)
  21. {
  22. return;
  23. }
  24. if(!ExceptionType.IsInstanceOfType(exception))
  25. {
  26. return;
  27. }
  28. stringcontrollerName=(string)filterContext.RouteData.Values["controller"];
  29. stringactionName=(string)filterContext.RouteData.Values["action"];
  30. HandleErrorInfomodel=newHandleErrorInfo(filterContext.Exception,controllerName,actionName);
  31. filterContext.Result=newViewResult
  32. {
  33. ViewName=View,
  34. MasterName=Master,
  35. ViewData=newViewDataDictionary<HandleErrorInfo>(model),
  36. TempData=filterContext.Controller.TempData
  37. };
  38. filterContext.ExceptionHandled=true;
  39. filterContext.HttpContext.Response.Clear();
  40. filterContext.HttpContext.Response.StatusCode=500;
  41. //CertainversionsofIISwillsometimesusetheirownerrorpagewhen
  42. //theydetectaservererror.Settingthispropertyindicatesthatwe
  43. //wantittotrytorenderASP.NETMVC‘serrorpageinstead.
  44. filterContext.HttpContext.Response.TrySkipIisCustomErrors=true;
  45. }

Application_Start中将HandleErrorAttribute添加到全局筛选器GlobalFilterCollection中,系统即会对异常进行对应的处理。
我们现在实现一个自定义的异常处理筛选器,在处理完后记录异常信息至日志文件中 
[csharp]view plaincopy
  1. publicclassMyExceptionHandleAttribute:HandleErrorAttribute
  2. {
  3. publicMyExceptionHandleAttribute()
  4. :base()
  5. {
  6. }
  7. publicvoidOnException(ExceptionContextfilterContext)
  8. {
  9. base.OnException(filterContext);
  10. //记录日志
  11. log.Info(filterContext.Exception);
  12. }
  13. }

在GlobalFilterCollection添加MyExceptionHandleAttribute即可使用自定义的异常筛选器来处理

ActionFilter筛选器

ActionFilter筛选器是在Action方法执行前后会触发,主要用于在Action执行前后处理一些相应的逻辑。ActionFilter的筛选器都继承于ActionFilterAttribute抽象类,而它实现了IActionFilter、IResultFilter和FilterAttribute类,结构如下

因此自定义ActionFilter筛选器只要继承ActionFilterAttribute,实现其中的方法即可。

我们来举一个简单的例子,获取Action方法的执行时长,代码如下

[csharp]view plaincopy
  1. publicclassDefaultController:Controller
  2. {
  3. [ActionExecTimeSpan]
  4. publicActionResultDoWork()
  5. {
  6. returnView();
  7. }
  8. }
  9. publicclassActionExecTimeSpanAttribute:ActionFilterAttribute
  10. {
  11. privateconststringexecuteActionTimeKey="ActionExecBegin";
  12. publicoverridevoidOnActionExecuting(ActionExecutingContextfilterContext)
  13. {
  14. base.OnActionExecuting(filterContext);
  15. //记录开始执行时间
  16. filterContext.HttpContext.Items[executeActionTimeKey]=DateTime.Now;
  17. }
  18. publicoverridevoidOnActionExecuted(ActionExecutedContextfilterContext)
  19. {
  20. //计算执行时间,并记录日志
  21. if(filterContext.HttpContext.Items.Contains(executeActionTimeKey))
  22. {
  23. DateTimeendTime=DateTime.Now;
  24. DateTimebeginTime=Convert.ToDateTime(filterContext.HttpContext.Items[executeActionTimeKey]);
  25. TimeSpanspan=endTime-beginTime;
  26. doubleexecTimeSpan=span.TotalMilliseconds;
  27. log.Info(execTimeSpan+"毫秒");
  28. }
  29. //
  30. base.OnActionExecuted(filterContext);
  31. }
  32. }

ResultFilter筛选器

ResultFilter筛选器是对Action方法返回的Result结果进行执行时触发的。它也分执行前和执行后两个段执行

所有的ResultFilter都实现了IResultFilter接口和FilterAttribute类,看一下接口定义

[csharp]view plaincopy
  1. publicinterfaceIResultFilter
  2. {
  3. voidOnResultExecuting(ResultExecutingContextfilterContext);
  4. voidOnResultExecuted(ResultExecutedContextfilterContext);
  5. }
其中OnResultExecuting和OnResultExecuted方法分别是在Result执行前、后(页面展示内容生成前、后)触发。使用ResultFilter筛选器最典型的应用就是页面静态化,我们以后在其他文章中在对此进行详细讲解

MVC四大筛选器—ActionFilter&ResultedFilter

原文地址:https://www.cnblogs.com/jjg0519/p/8759221.html

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved