ASP.NET Core MVC 从入门到精通之Filter

简介: ASP.NET Core MVC 从入门到精通之Filter

随着技术的发展,ASP.NET Core MVC也推出了好长时间,经过不断的版本更新迭代,已经越来越完善,本系列文章主要讲解ASP.NET Core MVC开发B/S系统过程中所涉及到的相关内容,适用于初学者,在校毕业生,或其他想从事ASP.NET Core MVC 系统开发的人员。

经过前几篇文章的讲解,初步了解ASP.NET Core MVC项目创建,启动运行,以及命名约定,创建控制器,视图,模型,接收参数,传递数据ViewData,ViewBag,路由,页面布局,wwwroot和客户端库,Razor语法,EnityFrameworkCore与数据库,HttpContext,Request,Response,Session,序列化,文件上传,自动映射,Html辅助标签,模型校验,鉴权、授权基础,Identity入门,日志管理等内容,今天继续讲解ASP.NET Core MVC 中Filter(筛选器)等相关内容,仅供学习分享使用。

什么是Filter?

Filter又称为筛选器,过滤器。在ASP.NET Core MVC项目中,通过使用Filter,可以在请求处理管道的特定位置之前或之后运行代码。可以创建自定义Filter,用于处理横切关注点,类似于AOP面向切面编程。对于创建Filter,可以减少代码的复制,例如,错误处理异常筛选器可以合并错误处理。

Filter工作原理

从请求开始,到请求结束,经过一系列的节点,组成了调用管道。Filter在ASP.NET Core MVC的调用管道内运行,过滤器相当于在管道中设置的几个钩子,用于执行特定的代码。

Filter类型

根据不同的处理功能,筛选器主要分为以下几类:

  • 授权筛选器AuthorizationFilter:
  • 首先运行。
  • 确定用户是否获得请求授权。
  • 如果请求未获授权,可以让管道短路。
  • 资源筛选器Resource Filter:
  • 授权后运行。
  • OnResourceExecuting 在筛选器管道的其余阶段之前运行代码。 例如,OnResourceExecuting 在模型绑定之前运行代码。
  • OnResourceExecuted 在管道的其余阶段完成之后运行代码。
  • 操作筛选器Action Filter:
  • 在调用操作方法之前和之后立即运行。
  • 可以更改传递到操作中的参数。
  • 可以更改从操作返回的结果。
  • 不可在 Razor Pages 中使用。
  • 异常筛选器Exception Filter:在向响应正文写入任何内容之前,对未经处理的异常应用全局策略。
  • 结果筛选器Result Filter:
  • 在执行操作结果之前和之后立即运行。
  • 仅当操作方法成功执行时才会运行。
  • 对于必须围绕视图或格式化程序的执行的逻辑,会很有用。

下图展示了Filter筛选器类型在筛选器管道中的交互方式:

Filter实现

所有的Filter都实现接口IFilterMetadata,根据不同的业务类型,派生出了五个接口,分别对应五大类Filter,如下所示:

注意:上述五个接口还有对应异步接口(Async)。

Filter作用域

Filter可以作用在Controller,Action,全局。下面的示例阐释了为同步操作筛选器运行筛选器方法的顺序:

授权Filter

授权筛选器:

  • 是筛选器管道中运行的第一个筛选器。
  • 控制对操作方法的访问。
  • 具有在它之前的执行的方法,但没有之后执行的方法。

如常用的RequireHttps就是授权筛选器,它实现了IAuthorizationFilter接口,并继承了Attirbute,所以可以作用于Controller或Action中。以限制请求的方式。

using Microsoft.AspNetCore.Mvc.Filters;
using System;
namespace Microsoft.AspNetCore.Mvc
{
    //
    // 摘要:
    //     An authorization filter that confirms requests are received over HTTPS.
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public class RequireHttpsAttribute : Attribute, IAuthorizationFilter, IFilterMetadata, IOrderedFilter
    {
        public RequireHttpsAttribute();
        public int Order { get; set; }
        public virtual void OnAuthorization(AuthorizationFilterContext filterContext);
        protected virtual void HandleNonHttpsRequest(AuthorizationFilterContext filterContext);
    }
}

资源Filter

资源Filter在授权Filter之后执行,需要实现IResourceFilter接口。如下所示:

using Microsoft.AspNetCore.Mvc.Filters;
namespace DemoCoreMVC.Filter
{
    /// <summary>
    /// 同步版本
    /// </summary>
    public class LogResourceFilter :Attribute, IResourceFilter
    {
        public void OnResourceExecuted(ResourceExecutedContext context)
        {
            //Action执行完成后执行
            Console.WriteLine("********************On Resource Filter Executed********************");
        }
        public void OnResourceExecuting(ResourceExecutingContext context)
        {
            //授权Filter执行后执行。
            Console.WriteLine("********************On Resource Filter Executing********************");
        }
    }
    /// <summary>
    /// 异步版本
    /// </summary>
    public class AsynLogResouceFilter : Attribute, IAsyncResourceFilter
    {
        public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
        {
            Console.WriteLine("********************On Aysnc Resource Filter Executing********************");
            var exceutedContext =  await next();
            Console.WriteLine("********************On Async Resource Filter Executed********************");
        }
    }
}

如果要使大部分管道短路,资源筛选器会很有用。 例如,如果缓存命中,则缓存筛选器可以绕开管道的其余阶段。

操作Filter

操作筛选器不应用于 Razor Pages。 Razor Pages 支持 IPageFilter 和 IAsyncPageFilter。

操作筛选器:

  • 实现 IActionFilter 或 IAsyncActionFilter 接口。
  • 它们的执行围绕着操作方法的执行。

以下代码显示示例操作筛选器:

using Microsoft.AspNetCore.Mvc.Filters;
namespace DemoCoreMVC.Filter
{
    public class DoDoActionFilter : Attribute, IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext context)
        {
            Console.WriteLine("********************On Action Executed********************");
        }
        public void OnActionExecuting(ActionExecutingContext context)
        {
            Console.WriteLine("********************On Action Executing********************");
        }
    }
    public class AsyncDoDoActionFilter : IAsyncActionFilter
    {
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            Console.WriteLine("********************On Async Action Executing********************");
            await next();
            Console.WriteLine("********************On Async Action Executed********************");
        }
    }
}

ActionExecutingContext 提供以下属性:

  • ActionArguments - 用于读取操作方法的输入。
  • Controller - 用于处理控制器实例。
  • Result - 设置 Result 会使操作方法和后续操作筛选器的执行短路。

ActionExecutedContext 提供 ControllerResult 以及以下属性:

  • Canceled - 如果操作执行已被另一个筛选器设置短路,则为 true。
  • Exception - 如果操作或之前运行的操作筛选器引发了异常,则为非 NULL 值。 将此属性设置为 null:
  • 有效地处理异常。
  • 执行 Result,从操作方法中将它返回。

对于 IAsyncActionFilter,一个向 ActionExecutionDelegate 的调用可以达到以下目的:

  • 执行所有后续操作筛选器和操作方法。
  • 返回 ActionExecutedContext

异常Filter

异常筛选器:

  • 实现 IExceptionFilter 或 IAsyncExceptionFilter。
  • 可用于实现常见的错误处理策略。

下面的异常筛选器示例显示在开发应用时发生的异常的相关详细信息:

using Microsoft.AspNetCore.Mvc.Filters;
namespace DemoCoreMVC.Filter
{
    public class DoExceptionFilter :Attribute, IExceptionFilter
    {
        public void OnException(ExceptionContext context)
        {
            Console.WriteLine("********************On Exception********************");
        }
    }
    public class DoAsyncExceptionFilter : Attribute, IAsyncExceptionFilter
    {
        public async Task OnExceptionAsync(ExceptionContext context)
        {
            await Task.Run(() =>
            {
                Console.WriteLine("********************On Exception Async********************");
            });
        }
    }
}

异常筛选器:

  • 没有之前和之后的事件。
  • 实现 OnException 或 OnExceptionAsync。
  • 处理 Razor 页面或控制器创建、模型绑定、操作筛选器或操作方法中发生的未经处理的异常。
  • 请不要捕获资源筛选器、结果筛选器或 MVC 结果执行中发生的异常。

若要处理异常,请将 ExceptionHandled 属性设置为 true 或分配 Result 属性。 这将停止传播异常。 异常筛选器无法将异常转变为“成功”。 只有操作筛选器才能执行该转变。

异常筛选器:

  • 非常适合捕获发生在操作中的异常。
  • 并不像错误处理中间件那么灵活。

建议使用中间件处理异常。 基于所调用的操作方法,仅当错误处理不同时,才使用异常筛选器。 例如,应用可能具有用于 API 终结点和视图/HTML 的操作方法。 API 终结点可以将错误信息返回为 JSON,而基于视图的操作可能会以 HTML 形式返回错误页。

结果Filter

结果筛选器:

  • 实现接口:
  • IResultFilter 或 IAsyncResultFilter
  • IAlwaysRunResultFilter 或 IAsyncAlwaysRunResultFilter
  • 它们的执行围绕着操作结果的执行。
using Microsoft.AspNetCore.Mvc.Filters;
namespace DemoCoreMVC.Filter
{
    public class DoResultFilter :Attribute, IResultFilter
    {
        public void OnResultExecuted(ResultExecutedContext context)
        {
            Console.WriteLine("********************On Result Executed********************");
        }
        public void OnResultExecuting(ResultExecutingContext context)
        {
            Console.WriteLine("********************On Result Executing********************");
        }
    }
    public class DoAysncResultFilter :Attribute, IAsyncResultFilter
    {
        public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
        {
            Console.WriteLine("********************On Result Execution Async Executing********************");
            await next();
            Console.WriteLine("********************On Result Execution Async Executed********************");
        }
    }
}

Filter测试

将写好的过滤器,放在Home/Index上,如下所示:

[DoExceptionFilter]
[LogResourceFilter]
[DoResultFilter]
[DoDoActionFilter]
public IActionResult Index()
{
    _logger.LogInformation("Hello, 这是首页!");
    return View();
}

测试如下所示:

说明:异常过滤器没有输出内容,是因为没有异常产生。授权过滤器没有添加,在所有过滤器之前开始,所有过滤器之后结束。

Filter全局应用

Filter可以应用在单个Controller或Action上,也可以进行全局应用,代码如下所示:

builder.Services.AddControllersWithViews(option =>
{
    option.Filters.Add<LogResourceFilter>();
    option.Filters.Add<DoExceptionFilter>();
    option.Filters.Add<DoResultFilter>();
    option.Filters.Add<DoDoActionFilter>();
});

全局测试如下所示:

以上就是ASP.NET Core MVC 从入门到精通之Filter的全部内容。

参考文档

官方文档:https://learn.microsoft.com/zh-cn/aspnet/core/mvc/controllers/filters?view=aspnetcore-6.0

相关文章
|
4天前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
5天前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
17 3
|
26天前
|
开发框架 NoSQL .NET
利用分布式锁在ASP.NET Core中实现防抖
【9月更文挑战第5天】在 ASP.NET Core 中,可通过分布式锁实现防抖功能,仅处理连续相同请求中的首个请求,其余请求返回 204 No Content,直至锁释放。具体步骤包括:安装分布式锁库如 `StackExchange.Redis`;创建分布式锁服务接口及其实现;构建防抖中间件;并在 `Startup.cs` 中注册相关服务和中间件。这一机制有效避免了短时间内重复操作的问题。
|
2月前
|
开发框架 监控 .NET
开发者的革新利器:ASP.NET Core实战指南,构建未来Web应用的高效之道
【8月更文挑战第28天】本文探讨了如何利用ASP.NET Core构建高效、可扩展的Web应用。ASP.NET Core是一个开源、跨平台的框架,具有依赖注入、配置管理等特性。文章详细介绍了项目结构规划、依赖注入配置、中间件使用及性能优化方法,并讨论了安全性、可扩展性以及容器化的重要性。通过这些技术要点,开发者能够快速构建出符合现代Web应用需求的应用程序。
35 0
|
2月前
|
缓存 数据库连接 API
Entity Framework Core——.NET 领域的 ORM 利器,深度剖析其最佳实践之路
【8月更文挑战第28天】在软件开发领域,高效的数据访问与管理至关重要。Entity Framework Core(EF Core)作为一款强大的对象关系映射(ORM)工具,在 .NET 开发中扮演着重要角色。本文通过在线书店应用案例,展示了 EF Core 的核心特性和优势。我们定义了 `Book` 实体类及其属性,并通过 `BookStoreContext` 数据库上下文配置了数据库连接。EF Core 提供了简洁的 API,支持数据的查询、插入、更新和删除操作。
62 0
|
2月前
|
开发框架 监控 .NET
【Azure 应用程序见解】在Docker中运行的ASP.NET Core应用如何开启Application Insights的Profiler Trace呢?
【Azure 应用程序见解】在Docker中运行的ASP.NET Core应用如何开启Application Insights的Profiler Trace呢?
|
2月前
|
Linux C# C++
【Azure App Service For Container】创建ASP.NET Core Blazor项目并打包为Linux镜像发布到Azure应用服务
【Azure App Service For Container】创建ASP.NET Core Blazor项目并打包为Linux镜像发布到Azure应用服务
|
2月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
36 0
|
2月前
|
开发框架 .NET API
如何在 ASP.NET Core Web Api 项目中应用 NLog 写日志?
如何在 ASP.NET Core Web Api 项目中应用 NLog 写日志?
|
2月前
|
开发框架 中间件 .NET
分享 ASP.NET Core Web Api 中间件获取 Request Body 两个方法
分享 ASP.NET Core Web Api 中间件获取 Request Body 两个方法
下一篇
无影云桌面