ASP.NET Core 中的五种过滤器

news/2024/5/20 0:28:37 标签: c#, asp.net, 后端, restful, .netcore

ASP.NET Core 中的五种过滤器

  • 前言
  • 一、过滤器介绍
    • 1.五种过滤器
      • (1)IActionFilter
      • (2)IAuthorizationFilter
      • (3)IExceptionFilter
      • (4)IResourceFilter
      • (5)IResultFilter
    • 2.另外两种过滤器
      • (1)IOrderedFilter
      • (2)IPageFilter
    • 3.三个特性
      • (1)ActionFilterAttribute
      • (2)ExceptionFilterAttribute
      • (3)ResultFilterAttribute
  • 二、过滤器演示代码
    • 1.实现接口
      • (1)ActionFilter1Attribute.cs
      • (2)ActionFilter2Attribute.cs
      • (3)AuthorizationFilterAttribute.cs
      • (4)ExecptionFilter.cs
      • (5)ResourceFilterAttribute.cs
      • (6)ResultFilter1Attribute.cs
      • (7)综合测试
    • 2.继承类
      • (1)LogActionFilter.cs
      • (2)ResultFilter.cs


前言

👨‍💻👨‍🌾📝记录学习成果,以便温故而知新

本文以命名空间Microsoft.AspNetCore.Mvc.Filters下的过滤器学习的过程做一个记录。广大网友们都说是过滤器,Java里貌似也说是过滤器,所以就顺着大家叫了。但是官网上却是叫“筛选器”。

Microsoft.AspNetCore.Mvc.Filters 命名空间官网:https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.mvc.filters?view=aspnetcore-7.0

讲实话,微软的官网现在感觉有点凌乱,有些看似官网的却是志愿者还是啥的写的内容。所以如果有什么差错还请谅解。


一、过滤器介绍

1.五种过滤器

广大网友们所说的五种过滤器,当然它们都有对应的异步过滤器。由于学习是循序渐进的,先学习同步的,等掌握好了以后再去学习异步的。

(1)IActionFilter

环绕操作执行的筛选器。

两个方法:

1.OnActionExecuted(ActionExecutedContext)

在操作执行后、操作结果之前调用。

2.OnActionExecuting(ActionExecutingContext)

在操作执行之前调用,在模型绑定完成后调用。

(2)IAuthorizationFilter

确认请求授权的筛选器。

一个方法:

OnAuthorization(AuthorizationFilterContext)

在筛选器管道的早期调用,以确认请求是否已获得授权。

(3)IExceptionFilter

在操作引发 Exception后运行的筛选器。

一个方法:

OnException(ExceptionContext)

在操作引发 Exception后调用 。

(4)IResourceFilter

包含模型绑定执行的筛选器、操作 (和筛选器) 以及操作结果 (和筛选器) 。

两个方法:

1.OnResourceExecuted(ResourceExecutedContext)

执行资源筛选器。 在执行管道的其余部分后调用。

2.OnResourceExecuting(ResourceExecutingContext)

执行资源筛选器。 在执行管道的其余部分之前调用。

(5)IResultFilter

包含操作执行结果的筛选器已成功从操作返回。

IResultFilter 如果授权筛选器或资源筛选器使请求短路以阻止操作的执行,则不会执行 和 IAsyncResultFilter 实例。 IResultFilter. IResultFilter 在异常筛选器通过生成操作结果处理异常的情况下,也不会执行 和 IAsyncResultFilter 实现。

两个方法:

1.OnResultExecuted(ResultExecutedContext)

在操作结果执行之后调用。

2.OnResultExecuting(ResultExecutingContext)

在操作结果执行之前调用。

2.另外两种过滤器

官网中还有另外两种过滤器,不知道广大网友为什么不介绍,只能揣测是不常用。简单介绍如下:

(1)IOrderedFilter

一个筛选器,指定它应运行的相对顺序。

(2)IPageFilter

一个筛选器,用于包围页面处理程序方法的执行。 仅当对处理程序的类型进行修饰时,才会执行此筛选器,而不是在单个处理程序方法上执行。

3.三个特性

很奇怪的是看到很多网友介绍的文章在定义过滤器特性时都没有继承现成的特性,而是实现的接口。

(1)ActionFilterAttribute

异步包围操作的执行和操作结果的抽象筛选器。 子类应替代 、 OnActionExecuted(ActionExecutedContext) 或 OnActionExecutionAsync(ActionExecutingContext, ActionExecutionDelegate) (但不替代OnActionExecutionAsync(ActionExecutingContext, ActionExecutionDelegate)OnActionExecuting(ActionExecutingContext))以及其他两个之一。 同样,子类应替代 、 OnResultExecuted(ResultExecutedContext) 或 OnResultExecutionAsync(ResultExecutingContext, ResultExecutionDelegate) (但不能OnResultExecutionAsync(ResultExecutingContext, ResultExecutionDelegate))OnResultExecuting(ResultExecutingContext)以及其他两个之一。

(2)ExceptionFilterAttribute

在操作引发 Exception后异步运行的抽象筛选器。 子类必须替代 或,OnExceptionAsync(ExceptionContext)但不能同时重写OnException(ExceptionContext)两者。

我再次确认了上面这段的引用,官网是:
在这里插入图片描述
只能无语(我竟无言以对)!!!

(3)ResultFilterAttribute

异步包围操作结果执行的抽象筛选器。 子类必须替代 、 OnResultExecuted(ResultExecutedContext) 或 OnResultExecutionAsync(ResultExecutingContext, ResultExecutionDelegate) (但不能OnResultExecutionAsync(ResultExecutingContext, ResultExecutionDelegate)替代OnResultExecuting(ResultExecutingContext))和另外两个之一。

以上内容看似洋洋洒洒,实际上主要来源于官网。对于这些知识的定义,也只能相信官网,不可能自己发挥的。下面是代码演示,就有了发挥的空间。

二、过滤器演示代码

本文的演示环境是Win10,目标框架是.NET Core 2.1,建的是ASP.NET Core Web 应用程序。不同的环境可能会有差别。

1.实现接口

(1)ActionFilter1Attribute.cs

namespace TestFilter.Filter
{
    public class ActionFilter1Attribute : Attribute, IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext context)
        {
            Debug.WriteLine("ActionFilter1Attribute OnActionExecuted");
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            Debug.WriteLine("ActionFilter1Attribute OnActionExecuting");
        }
    }
}

(2)ActionFilter2Attribute.cs

namespace TestFilter.Filter
{
    public class ActionFilter2Attribute : Attribute, IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext context)
        {
            Debug.WriteLine("ActionFilter2Attribute OnActionExecuted");
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {
            Debug.WriteLine("ActionFilter2Attribute OnActionExecuting");
        }
    }
}

定义了两个过滤器是想看同时注册时的调用顺序,如下测试代码:

// GET: api/User/ShowAction1
[HttpGet("ShowAction1")]
[ActionFilter1, ActionFilter2]
public IActionResult ShowAction1()
{
    ContentResult cr = new ContentResult();
    cr.Content = "ShowAction1";
    return cr;
}

控制台输出:
在这里插入图片描述
交换一下过滤器的顺序的代码:

// GET: api/User/ShowAction2
[HttpGet("ShowAction2")]
[ActionFilter2, ActionFilter1]
public IActionResult ShowAction2()
{
    ContentResult cr = new ContentResult();
    cr.Content = "ShowAction2";
    return cr;
}

控制台输出:
在这里插入图片描述
两张截图对比一下,结果很清晰的,所以也用不着总结了。

这里是把特性加在方法上,是给单个方法注册过滤器,下面类似情况不再重复说明。

(3)AuthorizationFilterAttribute.cs

确认授权过滤器特性定义了一个属性,是像简单演示一下权限是如何传参的。记得Java的shiro框架中logical来说明权限数组是“与”逻辑还是“或”逻辑,这里就不细说了,只要明白套路就行。所谓“运用之妙,存乎一心”。

namespace TestFilter.Filter
{
    public class AuthorizationFilterAttribute : Attribute, IAuthorizationFilter
    {
        /// <summary>
        /// 权限
        /// </summary>
        private string[] Privilege { get; set; }

        public AuthorizationFilterAttribute(params string[] privilege)
        {
            Privilege = privilege;
        }

        public void OnAuthorization(AuthorizationFilterContext context)
        {
            Debug.WriteLine("权限数量:" + Privilege.Length);
            Debug.WriteLine("AuthorizationFilter OnAuthorization");
        }
    }
}

测试代码如下:

// GET: api/User/ShowAuthorization1
[HttpGet("ShowAuthorization1")]
[AuthorizationFilter]
public IActionResult ShowAuthorization1()
{
    ContentResult cr = new ContentResult();
    cr.Content = "Authorization1";
    return cr;
}

控制台输出如图:
在这里插入图片描述
又一段测试代码:

// GET: api/User/ShowAuthorization2
[HttpGet("ShowAuthorization2")]
 [AuthorizationFilter("Admin", "User")]
 public IActionResult ShowAuthorization2()
 {
     ContentResult cr = new ContentResult();
     cr.Content = "Authorization2";
     return cr;
 }

控制台输出:
在这里插入图片描述
这里用可变长参数给特性传参,模拟传"Admin"与"User"两类权限。

(4)ExecptionFilter.cs

由于异常处理通常是全局的,所以就没有定义成特性。

namespace TestFilter.Filter
{
    public class ExecptionFilter : IExceptionFilter
    {
        public void OnException(ExceptionContext context)
        {
            Debug.WriteLine(context.Exception);

            context.Result = new ObjectResult("ExceptionHandled ");
            context.ExceptionHandled = true;
        }
    }
}

在Startup.cs文件中ConfigureServices方法里注册全局过滤器

services.AddMvc(option => {
    option.Filters.Add<ExecptionFilter>();//全局异常
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

测试代码如下:

// GET: api/User/ShowException
[HttpGet("ShowException")]
public IActionResult ShowException()
{
    throw new Exception("ShowException");
}

控制台输出如图:
在这里插入图片描述
在集成开发环境中要点一下“继续”才能看到控制台的输出,否则流程会被阻塞。

(5)ResourceFilterAttribute.cs

namespace TestFilter.Filter
{
    public class ResourceFilterAttribute : Attribute, IResourceFilter

    {
        public void OnResourceExecuted(ResourceExecutedContext context)
        {
            Debug.WriteLine("ResourceFilterAttribute OnResourceExecuted");
        }

        public void OnResourceExecuting(ResourceExecutingContext context)
        {
            Debug.WriteLine("ResourceFilterAttribute OnResourceExecuting");
        }
    }
}

测试代码如下:

// GET: api/User/ShowResource
[HttpGet("ShowResource")]
[ResourceFilter]
public IActionResult ShowResource()
{
    ContentResult cr = new ContentResult();
    cr.Content = "ShowResource";
    return cr;
}

控制台输出如图:
在这里插入图片描述

(6)ResultFilter1Attribute.cs

namespace TestFilter.Filter
{
    public class ResultFilter1Attribute : Attribute, IResultFilter
    {
        public void OnResultExecuted(ResultExecutedContext context)
        {
            Debug.WriteLine("ResultFilterAttribute OnResultExecuted");
        }

        public void OnResultExecuting(ResultExecutingContext context)
        {
            Debug.WriteLine("ResultFilterAttribute OnResultExecuting");
        }
    }
}

测试代码如下:

// GET: api/User/ShowResult1
[HttpGet("ShowResult1")]
[ResultFilter1]
public IActionResult ShowResult1()
{
    ContentResult cr = new ContentResult();
    cr.Content = "ShowResult1";
    return cr;
}

在这里插入图片描述

(7)综合测试

测试代码:

// GET: api/User/Comprehensive
[HttpGet("Comprehensive")]
[ActionFilter1]
[AuthorizationFilter]
[ResourceFilter]
[ResultFilter1]
public IActionResult Comprehensive()
{
    ContentResult cr = new ContentResult();
    cr.Content = "Comprehensive";
    return cr;
}

控制台输出如图:
在这里插入图片描述
这张截图很能说明各种过滤器的执行顺序。
异常过滤器会阻断一些过滤器的执行,有兴趣的自己可以去测试一下。

2.继承类

(1)LogActionFilter.cs

这段代码来源于文章了解操作筛选器 (C#)“创建日志操作筛选器”一节,感觉很有趣,就借用了。

namespace TestFilter.Filter
{
    public class LogActionFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            Log("OnActionExecuting", filterContext.RouteData);
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            Log("OnActionExecuted", filterContext.RouteData);
        }

        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            Log("OnResultExecuting", filterContext.RouteData);
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            Log("OnResultExecuted", filterContext.RouteData);
        }


        private void Log(string methodName, RouteData routeData)
        {
            var controllerName = routeData.Values["controller"];
            var actionName = routeData.Values["action"];
            var message = String.Format("{0} controller:{1} action:{2}", methodName, controllerName, actionName);
            Debug.WriteLine(message, "Action Filter Log");
        }
    }
}

测试代码:

namespace TestFilter.Controllers.Api
{
    [Route("api/[controller]")]
    [ApiController]
    [LogActionFilter]
    public class RoleController : ControllerBase
    {
        // GET: api/Role/Show
        [HttpGet("Show")]
        public IActionResult Show()
        {
            ContentResult cr = new ContentResult();
            cr.Content = "Show";
            return cr;
        }
    }
}

控制台输出如图:
在这里插入图片描述
这里的代码一是想介绍一下在类上注册过滤器;二是简单介绍获取方法的信息,其实还可以获取方法的传参与返回,限于篇幅就不展开了;三是想展示一下ActionFilterAttribute类可以覆盖的内容。

(2)ResultFilter.cs

namespace TestFilter.Filter
{
    public class ResultFilter : ResultFilterAttribute
    {
        public override void OnResultExecuted(ResultExecutedContext context)
        {
            Debug.WriteLine("ResultFilter OnResultExecuted");
        }

        public override void OnResultExecuting(ResultExecutingContext context)
        {
            Debug.WriteLine("ResultFilter OnResultExecuting");
        }
    }
}

测试代码:

// GET: api/User/ShowResult2
[HttpGet("ShowResult2")]
[ResultFilter]
public IActionResult ShowResult2()
{
    ContentResult cr = new ContentResult();
    cr.Content = "ShowResult2";
    return cr;
}

控制台输出如图:
在这里插入图片描述
这里也是两个方法,没有发现明显区别。

因为考虑到异常一般是全局处理,所以没有研究ExceptionFilterAttribute,感觉如果项目定义自己的异常体系倒是有必要针对不同异常来做处理。


http://www.niftyadmin.cn/n/5113882.html

相关文章

vscode类似GitHub Copilot的插件推荐

由于GitHub Copilot前段时间学生认证的账号掉了很多&#xff0c;某宝激活也是价格翻了几倍&#xff0c;而却&#xff0c;拿来用一天就掉线&#xff0c;可以试试同类免费的插件哦。 例如&#xff1a;TabNine&#xff0c;下载插件后&#xff0c;他会提示你登录&#xff0c;直接登…

【GIS前言技术】到底什么是实景三维?

文章目录 什么是实景三维&#xff1f;实景三维是怎么制作的&#xff1f;实景三维有哪些应用&#xff1f; 什么是实景三维&#xff1f; 实景三维是客观真实反映现实世界的三维模型&#xff0c;具有单体化、实体化、结构化、语义化的特点&#xff0c;通过融合模型三维、倾斜三维…

老胡的周刊(第112期)

老胡的信息周刊[1]&#xff0c;记录这周我看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。 &#x1f3af; 项目 LocalAI[2] &#x1f916; 免费、开源的 Ope…

[计算机提升] 数据及相关概念

1.9 数据及相关概念 1.9.1 数据、信息 在Windows系统中&#xff0c;数据是指事实或信息的集合&#xff0c;可以是数字、文本、图像、声音等形式的内容。数据是计算机系统中处理和操作的基本元素&#xff0c;是信息的表现形式和载体。 与信息相比&#xff0c;数据的范围更广泛…

【原创】【指针】*p++与*++p不同的执行顺序

【核心】※p ※(p) ≠ ※p ※(p1) [※即*] 【易混关注】 ※(p) 与※(p1) →二者执行顺序不同&#xff0c;区分&#xff01; 【说明】※p ※ (p)都是先执行p※&#xff0c;再p&#xff08;即先取值&#xff0c;再指针后移&#xff09;&#xff1b;而 ※p和※&#xff08;p1)是先…

C# Onnx Yolov8 Detect 戴安全帽检测

效果 项目 代码 using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms;namespace Onnx…

快问快答:关于线上流量卡“归属地随机”几个问题!

在网上办过流量卡的朋友应该都知道&#xff0c;资费虽然便宜&#xff0c;但是归属地却是异地&#xff0c;今天小编就给大家聊一聊关于流量卡归属地的问题。 ​ 网上的流量卡都是归属地随机的卡&#xff0c;今天小编以问答的方式给大家普及一下&#xff0c;如果对于归属地有疑问…

iOS自动化测试方案(三):WDA+iOS自动化测试解决方案

文章目录 一、背景二、环境准备三、总结四、扩展4.1、WDA Client4.2、先使用WDA实现自动化4.3、代码示例&#xff1a;4.4、脱离macOS测试iOS App自动化&#xff0c;两个解决方案&#xff1a;4.5、第二种解决办法&#xff1a;pip install -U weditor4.6、下载安装Appium-Inspect…