ASP.NET MVC中Filter过滤器的使用

MVC Filter是典型的AOP(面向切面编程)应用,在ASP.NET MVC中的4个过滤器类型,如下:


但是默认实现它们的过滤器只有三种,分别是ActionFilter(方法),Authorize(授权),HandleError(错误处理)。

  • 特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。
  • 特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。.Net 框架提供了两种类型的特性:预定义特性和自定义特性

Filter的默认实现方式就是带有Attribute后缀的,有了Attribute,我们就可以将我们的Filter像标签一样的贴在方法或者控制器的上方

Web Api:   System.Web.Http.Filters.ActionFilterAttribute 继承该类

  • OnActionExecuting  执行前
  • OnActionExecuted   执行后
  • OnResultExecuting  返回前
  • OnResultExecuted   返回后

Mvc:   System.Web.Mvc.ActionFilterAttribute  继承该类

  • OnActionExecuting  执行前  
  • OnActionExecutingAsync  执行前(异步)
  • OnActionExecuted   执行后 
  •  OnActionExecutedAsync   执行后(异步)

1、Action过滤器在ASP.NET MVC中创建MvcApp项目,创建文件夹Filter,然后新建类MyActionFilterAttribute(为了遵循默认的约定,名称以Attribute结尾),继承自ActionFilterAttribute类。ActionFilterAttribute类有如下4个方法。

using System;
 
namespace System.Web.Mvc
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter
    {
 
        protected ActionFilterAttribute();
 
        public virtual void OnActionExecuted(ActionExecutedContext filterContext);
 
        public virtual void OnActionExecuting(ActionExecutingContext filterContext);
 
        public virtual void OnResultExecuted(ResultExecutedContext filterContext);
 
        public virtual void OnResultExecuting(ResultExecutingContext filterContext);
    }
}

实现MyActionFilterAttribute类:

using System;
using System.Web.Mvc;
 
namespace MvcApp.Filter
{
    public class MyActionFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //1、获取请求的类名和方法名
            string strController = filterContext.RouteData.Values["controller"].ToString();
            string strAction = filterContext.RouteData.Values["action"].ToString();
 
            //2、用另一种方式获取请求的类名和方法名
            string strController2 = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
            string strAction2 = filterContext.ActionDescriptor.ActionName;
 
            filterContext.HttpContext.Response.Write("控制器:" + strController + "<br/>");
            filterContext.HttpContext.Response.Write("控制器:" + strController2 + "<br/>");
            filterContext.HttpContext.Response.Write("Action:" + strAction + "<br/>");
            filterContext.HttpContext.Response.Write("Action:" + strAction2 + "<br/>");
 
            filterContext.HttpContext.Response.Write("Action执行前:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");
            base.OnActionExecuting(filterContext);
        }
 
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            filterContext.HttpContext.Response.Write("Action执行后:" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");
            base.OnActionExecuted(filterContext);
        }
    }
}

对于过滤器,我们可以把它们加在3个地方,一个是控制器上面(控制器下面的所有Action),一个是Action上面(指定标识的Action),另一个就是全局位置(所有控制器中的Action)。这里只演示在Action上面和Home控制器中:

[MyActionFilter]
public ActionResult Index()
{
    return View();
}

2、Result过滤器

新建MyResultFilterAttribute类,继承ActionFilterAttribute:

using System;
using System.Web.Mvc;
 
namespace MvcApp.Filter
{
    public class MyResultFilterAttribute : ActionFilterAttribute
    {
        /// <summary>
        /// 加载“视图”前执行
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            filterContext.HttpContext.Response.Write("加载视图前执行 OnResultExecuting" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");
            base.OnResultExecuting(filterContext);
        }
 
        /// <summary>
        /// 加载“视图”后执行
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            filterContext.HttpContext.Response.Write("加载视图后执行 OnResultExecuted" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + "<br/>");
            base.OnResultExecuted(filterContext);
        }
    }
}

这里把MyResultFilter过滤器加在控制器上面,相当于给Home控制器中的所有的Action方法添加了MyResultFilter过滤器。

using MvcApp.Filter;
using System.Web.Mvc;
 
namespace MvcApp.Controllers
{
    [MyResultFilter]
    public class HomeController : Controller
    {
        [MyActionFilter]
        public ActionResult Index()
        {
            return View();
        }
 
    }
}

3、AuthorizeAttribute过滤器

创建MyAuthorizeAttribute类,继承AuthorizeAttribute类:

using System.Web.Mvc;
 
namespace MvcApp.Filter
{
    /// <summary>
    /// 授权过滤器
    /// </summary>
    public class MyAuthorizeAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            filterContext.HttpContext.Response.Write("OnAuthorization<br/>");
 
            //注释掉父类方法,因为父类里的OnAuthorization方法会调用ASP.NET的授权验证机制
            //base.OnAuthorization(filterContext);
        }
 
    }
}

在控制器Home中的Index上添加MyAuthorize过滤器:

[MyAuthorize]
[MyActionFilter]
public ActionResult Index()
{
    return View();
}

通常Authorize过滤器也是在全局过滤器上面的,主要用来做登录验证或者权限验证,在App_Start目录下的FilterConfig类的RegisterGlobalFilters方法中添加:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        //filters.Add(new HandleErrorAttribute());
 
        //添加全局授权过滤器
        filters.Add(new MyAuthorizeAttribute());
    }
}

在全局中注册过滤器,则所有控制器的所有行为(Action)都会执行这个过滤器。

运行结果,如下图:

4、Exception过滤器

创建MyHandleErrorAttribute类,继承HandleErrorAttribute类:

using System;
using System.Web.Mvc;
 
namespace MvcApp.Filter
{
    /// <summary>
    /// 异常处理过滤器
    /// </summary>
    public class MyHandleErrorAttribute : HandleErrorAttribute
    {
        public override void OnException(ExceptionContext filterContext)
        { 
            //1、获取异常对象
            Exception ex = filterContext.Exception;
            
            //2、记录异常日志
 
            //3、重定向友好页面
            filterContext.Result = new RedirectResult("~/error.html");
 
            //4、标记异常已经处理完毕
            filterContext.ExceptionHandled = true;
 
            base.OnException(filterContext);
        }
    }
}

在Action上面添加MyHandleError过滤器:

[MyHandleError]
public ActionResult GetErr()
{
    int a = 0;
    int b = 1 / a;
    return View();
}

创建异常错误友好提示页面error.html。

<body>
    自定义错误页面
</body>

运行会自动跳转到error.html页面。

如果页面没有跳转,就需要去Web.config配置文件中的<system.web>节点下面添加如下配置节点,开启自定义错误:

<customErrors mode="On"></customErrors>

通常这样的异常处理是放在全局过滤器上面的,只要任意Action方法报错就会执行MyHandleError过滤器中的代码。

修改App_Start目录下面的FilterConfig类:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        //filters.Add(new HandleErrorAttribute());
 
        //添加全局授权过滤器
        filters.Add(new MyAuthorizeAttribute());
 
        //添加全局异常处理过滤器
        filters.Add(new MyHandleErrorAttribute());
    }
}

Global.asax下的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
 
namespace MvcApp
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/550083.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微服务之网关路由

一、概述 1.1认识网关 什么是网关&#xff1f; 顾明思议&#xff0c;网关就是网络的关口。数据在网络间传输&#xff0c;从一个网络传输到另一网络时就需要经过网关来做数据的路由和转发以及数据安全的校验。 更通俗的来讲&#xff0c;网关就像是以前园区传达室的大爷。 外…

Pytest精通指南(14)Parametrize之indirect(间接参数)

文章目录 官方概念概念分析官方示例示例分析验证indirect为True但不指定fixture验证indirect为True但不存在fixture 官方概念 概念分析 在pytest的pytest.mark.parametrize装饰器中&#xff0c;indirect参数用于指示是否应该从fixtures中解析参数值&#xff0c;而不是直接使用提…

OpenCV基本图像处理操作(五)——图像数据操作

数据读取 cv2.IMREAD_COLOR&#xff1a;彩色图像cv2.IMREAD_GRAYSCALE&#xff1a;灰度图像 import cv2 #opencv读取的格式是BGR import matplotlib.pyplot as plt import numpy as np %matplotlib inline imgcv2.imread(cat.jpg)数据显示 #图像的显示,也可以创建多个窗口 c…

视频汇聚/安防视频监控云平台EasyCVR云端录像播放与下载的接口调用方法

视频汇聚/安防视频监控云平台EasyCVR支持多协议接入、可分发多格式的视频流&#xff0c;平台支持高清视频的接入、管理、共享&#xff0c;支持7*24小时不间断监控。视频监控管理平台EasyCVR可提供实时远程视频监控、录像、回放与存储、告警、语音对讲、云台控制、平台级联、磁盘…

Flink学习(六)-容错处理

前言 Flink 是通过状态快照实现容错处理 一、State Backends 由 Flink 管理的 keyed state 是一种分片的键/值存储&#xff0c;每个 keyed state 的工作副本都保存在负责该键的 taskmanager 本地中。 一种基于 RocksDB 内嵌 key/value 存储将其工作状态保存在磁盘上&#x…

图像处理与视觉感知---期末复习重点(8)

文章目录 一、图像分类流程二、梯度方向直方图2.1 概述2.2 计算梯度方向直方图2.2.1 过程2.2.2 总结 三、SIFT 一、图像分类流程 流程&#xff1a;输入图像、预处理、特征提取、学习算法、类标。 二、梯度方向直方图 2.1 概述 1. 梯度方向直方图(Histogram of Oriented Gradie…

RabbitMQ交换机的类型

交换机类型 可以看到&#xff0c;在订阅模型中&#xff0c;多了一个exchange角色&#xff0c;而且过程略有变化&#xff1a; Publisher&#xff1a;生产者&#xff0c;不再发送消息到队列中&#xff0c;而是发给交换机 Exchange&#xff1a;交换机&#xff0c;一方面&#xff…

Backend - DRF 序列化(django-rest-framework)

目录 一、restful 、django-rest-framework 、swagger 三者的关系 &#xff08;一&#xff09;restful API&#xff08;REST API&#xff09; 1. rest 2. restful 3. api 4. restfulAPI &#xff08;二&#xff09;django-rest-framework&#xff08;简称DRF&#xff09…

中立分析腾讯云故障相关的事件

最近腾讯云的故障&#xff0c;让一堆云计算爱好者兴奋地远看指点江山、近看沐猴而冠。我比这群爱好者们更了解云计算&#xff0c;但是我尊重我的读者&#xff0c;你们从我这里看到的科普信息&#xff0c;不仅仅只有情绪价值。 在信息爆炸的时代&#xff0c;大家关注和信任某个媒…

如何使用docker-compose安装数据可视化应用JSON Crack并实现远程访问

文章目录 1. 在Linux上使用Docker安装JSONCrack2. 安装Cpolar内网穿透工具3. 配置JSON Crack界面公网地址4. 远程访问 JSONCrack 界面5. 固定 JSONCrack公网地址 JSON Crack 是一款免费的开源数据可视化应用程序&#xff0c;能够将 JSON、YAML、XML、CSV 等数据格式可视化为交互…

微服务中的重要模块

为什么要有微服务&#xff1f; 微服务提高开发效能&#xff0c;避免业务的重复理解&#xff0c;代码重复开发&#xff0c;增加开发效能和代码复用性。 在实际的工作中许多不同的业务有着共同的功能需求&#xff0c;如果我们每遇到一次这种需求就重新去理解构建一次的话会花费大…

msyql中SQL 错误 [1118] [42000]: Row size too large (> 8126)

场景&#xff1a; CREATE TABLE test-qd.eqtree (INSERT INTO test.eqtree (idocid VARCHAR(50) NULL,sfcode VARCHAR(50) NULL,sfname VARCHAR(50) NULL,sfengname VARCHAR(50) NULL,…… ) ENGINEInnoDB DEFAULT CHARSETutf8 COLLATEutf8_general_ci;或 alter table eqtre…

Ctex+texmaker

最近要准备幻灯片&#xff0c;发现我喜欢的模板是用的Ctex&#xff0c;在Texlive下没有办法运行。 于是进行了很多尝试。最后找到一个快捷的办法&#xff0c;删掉自己笔记本中的texlive&#xff0c;在Ctex官网中下载Ctex套件(下载中心 – CTEX)&#xff0c;下载的版本是过时版…

Linux 安装KVM虚拟机

什么是KVM虚拟机&#xff1f; KVM 是 Kernel-based Virtual Machine 的缩写&#xff0c;是一种用于虚拟化的开源硬件虚拟化技术。它使用 Linux 内核的虚拟化模块&#xff0c;将物理服务器划分为多个虚拟机。KVM 允许虚拟机直接访问物理硬件资源,从而提供出色的性能和稳定性,同…

解读科技智慧公厕改变生活的革命性创新之路

公共厕所&#xff0c;作为城市基础设施的一部分&#xff0c;一直以来都备受人们诟病。脏乱差、设施老旧、管理混乱&#xff0c;成为公共厕所长期存在的问题。然而&#xff0c;随着科技的不断进步&#xff0c;智慧公厕应运而生&#xff0c;为解决公厕难题&#xff0c;智慧公厕源…

BetterDisplay Pro for Mac 显示器校准和优化软件

BetterDisplay Pro for Mac是一款适用于Mac电脑的显示器校准和优化软件。它可以帮助用户校准显示器的颜色、亮度、对比度和伽马值等参数&#xff0c;使得显示器更加准确和清晰&#xff0c;提高用户的工作效率。 BetterDisplay Pro for Mac v2.0.11激活版下载 这款软件具有直观的…

电脑不能上网,宽带调制解调器出现问题如何处理

目录 一、问题说明 二、解决方案 一、问题说明 内网的设备能互联&#xff0c;内网的各个设备无法连外网。 电脑在检测网络时&#xff0c;出现以下提示&#xff1a; 二、解决方案 首先重启光猫&#xff08;我们是电信宽带&#xff09;。 如果还是有问题&#xff0c;再重启…

springboot+vue全栈开发【3.前端篇之Vue基础语法2】

目录 前言Vue基础语法1.事件绑定指令2.条件渲染指令v-show和v-if指令v-else和v-else-if指令 3.列表渲染指令扩展&#xff1a;v-for中的key 前言 hi&#xff0c;这个系列是我自学开发的笔记&#xff0c;适合具有一定编程基础&#xff08;html、css那些基础知识要会&#xff01;…

MAC安装CocoaPods遇到的错误Failed to build gem native extension.

MAC安装CocoaPods遇到的错误Failed to build gem native extension. 配置flutter环境的时候报错cocoapods不可用 发现已经安装了CocoaPods&#xff0c;但是不能用 重新安装CocaPods sudo gem install cocoapods重新安装报错如下&#xff1a; 安装RVM curl -L https://get.r…

HBase的数据模型与架构

官方文档&#xff1a;Apache HBase – Apache HBase™ Homehttps://hbase.apache.org/ 一、HBase概述 1.概述 HBase的技术源自Google的BigTable论文&#xff0c;HBase建立在Hadoop之上&#xff0c;是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统&#xff0c;用于…