当前位置: 首页 > news >正文

.NET MVC之AOP

一. 简介、
MVC中的过滤器可以说是MVC框架中的一种灵魂所在,它是MVC框架中AOP思想的具体体现,所以它以面向切面的形式无侵入式的作用于代码的业务逻辑,与业务逻辑代码分离,一经推出,广受开发者的喜爱。

那么过滤器到底是什么呢?它又有什么作用呢?

用户通过URL访问Web系统不一定都能得到相应的内容,一方面不同的用户权限不同,另一方面是为了保护系统,防止被攻击,这就是过滤器的核心所在,我们总计一下过滤器都有哪些作用:

①:判断用户是否登录以及不同用户对应不同的权限问题。

②:防盗链、防爬虫。

③:系统中语言版本的切换(本地化和国际化)。

④:权限管理系统中动态Action。

⑤:决策输出缓存。

知道到了过滤器的作用,那么过滤器分哪几类呢?如下图1:
  在这里插入图片描述
二. 执行顺序
从上图①可知,过滤器分四类,总共重写了六个方法,在这六个方法里可以处理相应的业务逻辑,那么如果四种过滤器的六个重写方法同时存在,它们的执行顺序是什么呢?

首先要将OnException方法除外,该方法不和其余五个方法参与排序问题,该方法独立存在,什么时间报错,什么时候调用。

其余三种过滤器中的五个重写方法的执行顺序:
  在这里插入图片描述
三. 自定义实现形式

  1. 直接在控制器中重写方法或者利用控制器间的继承

新建任何一个控制器,它均继承Controller类,F12进入Controller类中,发现Controller类中已经实现了过滤器需要实现的接口,并且提供虚方法供我们重写,代码如下:
  在这里插入图片描述
  在这里插入图片描述
基于以上原理,这样在控制器级别上我们就有两种思路来实现过滤器。

方案一:直接在当前控制器重写相应的过滤器方法,则该过滤器的方法作用于当前控制器的所有Action
  在这里插入图片描述
方案二:新建一个父类控制器,在父类控制器中重写过滤器的方法,然后子类控制器继承该父类控制器,则该该过滤器作用于子类控制器中的所有Action。

【该方法和接下来以特性的形式作用于控制器的效果是一致的】
  ///
/// 控制器继承该控制器,和特性作用在控制器上效果一致
///
public class MyBaseFilterController : Controller
{
//需要用protected类型,不能用public类型
protected override void OnAuthorization(AuthorizationContext filterContext)
{
//1.如果保留如下代码,则会运行.net framework定义好的身份验证,如果希望自定义身份验证,则删除如下代码
// base.OnAuthorization(filterContext);

        //2.获取区域名字
        // string strAreaName = filterContext.RouteData.DataTokens["area"].ToString().ToLower();

        //3.获取控制器作用的Controller和action的名字
        string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.ToLower();
        string actionName = filterContext.ActionDescriptor.ActionName.ToLower();
        filterContext.HttpContext.Response.Write("身份验证过滤器作用于" + controllerName + "控制器下的" + actionName + "方法</br>");
    }
}
  1. 自定义类继承MVC中过滤器实现类或过滤器接口,特性的形式作用于控制器或Action

特别补充:MVC框架中的AuthorizeAttirbute、ActionFilterAttribute、HandleErrorAttribute类已经实现了过滤器对应的接口,所以我们在自定义过滤器的时候,可以直接继承以上三个类;或者实现相应的接口:IAuthorizationFilter、IActionFilter、IResultFilter、IExceptionFilter。(该方案在实现相应接口的同时,需要继承FilterAttribute,使自定义的类成为一个特性)。

在这里插入图片描述
  下面以继承MVC中实现类的形式来自定义四种过滤器:
  A:身份验证过滤器
  ///
/// 身份验证过滤器
/// 1. 在非MVC框架项目中使用MVC过滤器,需要通过nuget把MVC的程序集添加进去
/// 2. 继承AuthorizeAttribute类,然后对OnAuthorization方法进行 override 覆写
/// 3. 在Action运行之前首先运行该过滤器
///
public class MyAuthorize : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
//1.如果保留如下代码,则会运行.net framework定义好的身份验证,如果希望自定义身份验证,则删除如下代码
// base.OnAuthorization(filterContext);

        //2.获取区域名字
        // string strAreaName = filterContext.RouteData.DataTokens["area"].ToString().ToLower();

        //3.获取控制器作用的Controller和action的名字
        string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.ToLower();
        string actionName = filterContext.ActionDescriptor.ActionName.ToLower();
        filterContext.HttpContext.Response.Write("身份验证过滤器作用于" + controllerName + "控制器下的" + actionName + "方法</br>");
    }
}
**B:   行为过滤器**
/// <summary>
/// 行为过滤器
/// 1. 在非MVC框架项目中使用MVC过滤器,需要通过nuget把MVC的程序集添加进去
/// 2. 继承ActionFilterAttribute类,然后对OnActionExecuting方法和OnActionExecuted方法进行 override 覆写
/// 3. OnActionExecuting方法:在action方法运行之前,且OnAuthorization过滤器运行之后调用
///    OnActionExecuted方法:在action方法运行之后调用
/// </summary>
public class MyAction: ActionFilterAttribute
{

    /// <summary>
    /// 在action方法运行之前调用
    /// </summary>
    /// <param name="filterContext"></param>
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //1.如果保留如下代码,则会运行.net framework定义好的行为验证,如果希望自定义行为验证,则删除如下代码
        // base.OnActionExecuting(filterContext);

        //2.获取区域名字
        // string strAreaName = filterContext.RouteData.DataTokens["area"].ToString().ToLower();

        //3.获取控制器作用的Controller和action的名字
        string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.ToLower();
        string actionName = filterContext.ActionDescriptor.ActionName.ToLower();
        filterContext.HttpContext.Response.Write("行为过滤器OnActionExecuting作用于" + controllerName + "控制器下的" + actionName + "方法运行之前</br>");
    }
    /// <summary>
    /// 在action方法运行之后调用
    /// </summary>
    /// <param name="filterContext"></param>
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        //1.如果保留如下代码,则会运行.net framework定义好的行为验证,如果希望自定义行为验证,则删除如下代码
        // base.OnActionExecuted(filterContext);

        //2.获取区域名字
        // string strAreaName = filterContext.RouteData.DataTokens["area"].ToString().ToLower();

        //3.获取控制器作用的Controller和action的名字{ActionDescriptor对应的ControllerDescriptor}
        string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.ToLower();
        string actionName = filterContext.ActionDescriptor.ActionName.ToLower();
        filterContext.HttpContext.Response.Write("行为过滤器OnActionExecuted作用于" + controllerName + "控制器下的" + actionName + "方法运行之后</br>");
    }
}

C:结果过滤器
///
/// 结果过滤器
/// 1. 在非MVC框架项目中使用MVC过滤器,需要通过nuget把MVC的程序集添加进去
/// 2. 继承ActionFilterAttribute类,然后对OnResultExecuting方法和OnResultExecuted方法进行 override 覆写
/// 3. OnResultExecuting方法:在执行结果之后(action之后),页面渲染之前调用
/// OnResultExecuted方法:在页面渲染之后调用
///
public class MyResult : ActionFilterAttribute
{

    /// <summary>
    /// action执行之后(OnActionExecuting之后),页面渲染之前调用
    /// </summary>
    /// <param name="filterContext"></param>
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        //1.如果保留如下代码,则会运行.net framework定义好的结果验证,如果希望自定义结果验证,则删除如下代码
        // base.OnResultExecuting(filterContext);

        //该方法中无法获取是哪个控制器后
        filterContext.HttpContext.Response.Write("结果过滤器OnResultExecuting作用于action运行之后,页面加载之前");
    }
    /// <summary>
    /// 页面渲染之后调用
    /// </summary>
    /// <param name="filterContext"></param>
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        //1.如果保留如下代码,则会运行.net framework定义好的结果验证,如果希望自定义结果验证,则删除如下代码
        // base.OnResultExecuted(filterContext);

        //该方法中无法获取是哪个控制器后
        filterContext.HttpContext.Response.Write("结果过滤器OnResultExecuted作用于页面渲染之后");
    }
}
**D:异常过滤器**
 使用自定义异常处理,需要在web.config中为system.web添加<customErrors mode="On" />节点
 /// <summary>
/// 异常过滤器
/// 需要注意的点:
///   ①:如果自定义异常过滤器且需要有作用于全局,需要把FilterConfig中的 filters.Add(new HandleErrorAttribute());注释掉,
///       然后把自定义的异常过滤器添加到FilterConfig中。
///   ②:使用自定义异常处理,需要在web.config中为system.web添加<customErrors mode="On" />节点
/// </summary>
public class MyException: HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        //调用框架本身异常处理器的方法
        base.OnException(filterContext);

        //获取异常信息(可以根据实际需要写到本地或数据库中)
        var errorMsg = filterContext.Exception;

        //跳转指定的错误页面
        filterContext.Result = new RedirectResult("/error.html");
    }
}
下面展示以特性的形式作用于控制器或控制器中的Action:

在这里插入图片描述

3. 自定义类继承MVC中实现类或接口,全局注册,作用**于全部控制器**

 如果以上两种方式均不能满足你的过滤器的使用范围,你可以在App_Start文件夹下的FilterConfig类中进行全局注册,使该过滤器作用于所有控制器中所有Action方法。

特别注意的一点是:自定义异常过滤器,需要把系统默认的filters.Add(new HandleErrorAttribute());注释掉。
  全局注册的代码如下:
  public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
//如果自定义异常过滤器,需要把默认的异常过滤器给注释掉
//filters.Add(new HandleErrorAttribute());

        //自定义异常过滤器
        filters.Add(new MyException());

        //全局注册身份验证、行为、结果过滤器
        //filters.Add(new MyAuthorize());
        //filters.Add(new MyAction());
        //filters.Add(new MyResult());

        //全局注册登录验证(暂时注释,使用的时候要打开)
        //filters.Add(new CheckLogin());
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相关文章:

  • 机器学习基础
  • 浅谈报表测试
  • 第十一:Fiddler抓包教程(11)-Fiddler设置安卓手机抓包,不会可是万万不行的!
  • ARMv8 MMU和translation stages、translation regimes和相关寄存器
  • Linux入门之配置以太网连接
  • 小时3.0报表某个型号数据比天数据多问题复盘
  • 深度学习 FairMOT多目标跟踪(PANDA)
  • 深度学习图像分割U-Net和FCN讲解
  • MySQL语句(二)
  • MySQL中的重做日志(redo log),回滚日志(undo log),以及二进制日志(binlog)的作用及生成时机
  • python-读写Excel(三)-xlwt格式设置
  • 主从复制Slave_IO_Running: NO Slave_SQL_Running: NO 解决办法
  • 14对象的方法
  • 神经网络原理与实例精解,神经网络案例讲解范文
  • 【dfs爆搜】poj 1129 Channel Allocation
  • const let
  • CSS 提示工具(Tooltip)
  • ECMAScript 6 学习之路 ( 四 ) String 字符串扩展
  • gitlab-ci配置详解(一)
  • JavaScript学习总结——原型
  • 仿天猫超市收藏抛物线动画工具库
  • 后端_MYSQL
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 讲清楚之javascript作用域
  • 前端攻城师
  • 为物联网而生:高性能时间序列数据库HiTSDB商业化首发!
  • 继 XDL 之后,阿里妈妈开源大规模分布式图表征学习框架 Euler ...
  • 交换综合实验一
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​渐进式Web应用PWA的未来
  • ​水经微图Web1.5.0版即将上线
  • ###项目技术发展史
  • #考研#计算机文化知识1(局域网及网络互联)
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (附源码)ssm智慧社区管理系统 毕业设计 101635
  • (转)Oracle 9i 数据库设计指引全集(1)
  • (转)利用ant在Mac 下自动化打包签名Android程序
  • (最全解法)输入一个整数,输出该数二进制表示中1的个数。
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .net Application的目录
  • .Net CF下精确的计时器
  • .net MVC中使用angularJs刷新页面数据列表
  • .NET 发展历程
  • .NET 设计一套高性能的弱事件机制
  • .NET牛人应该知道些什么(2):中级.NET开发人员
  • .NET正则基础之——正则委托
  • .net中的Queue和Stack
  • :如何用SQL脚本保存存储过程返回的结果集
  • [AR Foundation] 人脸检测的流程
  • [autojs]逍遥模拟器和vscode对接
  • [C++]:for循环for(int num : nums)
  • [Codeforces] probabilities (R1600) Part.1
  • [Deepin 15] 编译安装 MySQL-5.6.35
  • [English]英语积累本