Filters in ASP.NET Core

如果觉得样式不好:跳转即可 (md文件复制过来有些样式会不一样)

原文地址:https://lifengying.site/archives/net6%E4%B9%8B%E8%BF%87%E6%BB%A4%E5%99%A8

Filters in ASP.NET Core

官网地址:https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-6.0&viewFallbackFrom=aspnetcore-2.2

Filter

ASP.NET Core 中的过滤器*允许代码在请求处理管道中的特定阶段之前或之后运行。

内置过滤器处理以下任务:

  • 授权,防止用户访问未经授权的资源。

  • 响应缓存,将请求管道短路以返回缓存的响应。

可以创建自定义过滤器来处理横切关注点。横切关注点的示例包括错误处理、缓存、配置、授权和日志记录。过滤器避免重复代码。例如,错误处理异常过滤器可以合并错误处理。

本文档适用于 Razor 页面、API 控制器和具有视图的控制器。过滤器不能直接与Razor 组件一起使用。过滤器只能在以下情况下间接影响组件:

  • 该组件嵌入在页面或视图中。

  • 页面或控制器和视图使用过滤器。

过滤器的工作原理

筛选器在ASP.NET Core 操作调用管道(有时称为筛选器管道)中运行。过滤器管道在 ASP.NET Core 选择要执行的操作后运行:

过滤器类型

每个过滤器类型在过滤器管道的不同阶段执行:

  • Authorization filters:

    • run first 最先执行

    • 确定用户是否有权执行请求。

    • 如果请求未经授权,则将管道短路。

  • Resource filters:

    • 授权后运行。

    • OnResourceExecuting在过滤器管道的其余部分之前运行代码。例如,OnResourceExecuting在模型绑定之前运行代码。

    • OnResourceExecuted在管道的其余部分完成后运行代码。

  • Action filters:

    • 在调用操作方法之前和之后立即运行。

    • 可以更改传递给动作的参数。

    • 可以更改从动作返回的结果。

    • Razor页面支持。

  • Exception filters

    将全局策略应用于在响应正文被写入之前发生的未处理异常。

  • Result filters:

    • 在执行动作结果之前和之后立即运行。

    • 仅在操作方法成功执行时运行。

    • 对于必须围绕视图或格式化程序执行的逻辑很有用。

下图显示了过滤器类型如何在过滤器管道中交互:

总结:

Authorization filters、Exception filters没有前后2种方法(仅限同步方法)

Resource filters、Action filters、Result filters 有前后2种方法(仅限同步方法)

如果是异步的,则与中间件类似

 before //等同于xxxExecuting
 await netx();//action 执行xxx方法
 after  //等同于xxxExecuted

Razor Pages 还支持Razor Page 过滤器,它们在 Razor Page 处理程序之前和之后运行。

例子:ActionFilters

同步
 using Microsoft.AspNetCore.Mvc.Filters;
 ​
 namespace FilterMvc.Filters
 {
     public class SampleActionFilter : IActionFilter
    {
         public void OnActionExecuting(ActionExecutingContext context)
        {
             // Do something before the action executes.
             Console.WriteLine("执行方法前做点什么呢?执行方法前");
        }
 ​
         public void OnActionExecuted(ActionExecutedContext context)
        {
             // Do something after the action executes.
             Console.WriteLine("执行方法后做点什么呢?执行方法后");
        }
    }
 }
异步:
 using Microsoft.AspNetCore.Mvc.Filters;
 ​
 namespace FilterMvc.Filters
 {
     public class SampleAsyncActionFilter : IAsyncActionFilter
    {
         public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
             // Do something before the action executes.
             Console.WriteLine("执行方法前做点什么呢?执行方法前");
             await next();
             // Do something after the action executes.
             Console.WriteLine("执行方法后做点什么呢?执行方法后");
        }
    }
 ​
 }

Multiple filter stages(复式filter)

多个过滤级的接口可以在单个类中实现。例如,ActionFilterAttribute类实现:

实现过滤器接口的同步异步版本,而不是两者。运行时首先检查过滤器是否实现了异步接口,如果是,则调用它。如果不是,它调用同步接口的方法。如果在一个类中同时实现异步和同步接口,则只调用 async 方法。使用ActionFilterAttribute等抽象类时,仅覆盖每个过滤器类型的同步方法或异步方法。

内置Attributes Filter (Built-in filter attributes)

ASP.NET Core 包括内置的基于属性的过滤器,可以进行子类化和自定义。例如,以下结果过滤器会在响应中添加一个标头:

 public class ResponseHeaderAttribute : ActionFilterAttribute
 {
     private readonly string _name;
     private readonly string _value;
 ​
     public ResponseHeaderAttribute(string name, string value) =>
        (_name, _value) = (name, value);
 ​
     public override void OnResultExecuting(ResultExecutingContext context)
    {
         context.HttpContext.Response.Headers.Add(_name, _value);
 ​
         base.OnResultExecuting(context);
    }
 }

属性允许过滤器接受参数,如前面的示例所示。将 应用于ResponseHeaderAttribute控制器或操作方法并指定 HTTP 标头的名称和值:

 [ResponseHeader("Filter-Header", "Filter Value")]
 public class ResponseHeaderController : ControllerBase
 {
     public IActionResult Index() =>
         Content("Examine the response headers using the F12 developer tools.");
 ​
     // ...
执行结果:

 using FilterMvc.Filters;
 using Microsoft.AspNetCore.Mvc;
 ​
 namespace FilterMvc.Controllers
 {
     public class ResponseHeaderController : Controller
    {
         /* public IActionResult Index()
           {
               return View();
           }
   */
        [ResponseHeader("Filter-Header", "Filter Value")]
         public IActionResult Index()
        {
            return Content("Examine the response headers using the F12 developer tools.");
        }
 ​
        [ResponseHeader("Another-Filter-Header", "Another Filter Value")]
         public IActionResult Multiple() =>
        Content("Examine the response headers using the F12 developer tools.");
 ​
    }
 }

该操作的响应Multiple包括以下标头:

  • filter-header: Filter Value

  • another-filter-header: Another Filter Value

一些过滤器接口具有相应的属性,可以用作自定义实现的基类。

Filter attributes:

Filter范围和执行顺序(Filter scopes and order of execution)

可以在以下三个范围*之一将过滤器添加到管道中:

  • 使用控制器或 Razor 页面上的属性。

  • 在控制器操作上使用属性。筛选器属性不能应用于 Razor 页面处理程序方法。

  • 全局用于所有控制器、操作和 Razor 页面,如以下代码所示:

     var builder = WebApplication.CreateBuilder(args);
     ​
     // Add services to the container.
     builder.Services.AddControllersWithViews(options =>
     {
         options.Filters.Add<GlobalSampleActionFilter>();
     });

    默认执行顺序

当管道的特定阶段有多个过滤器时,范围确定过滤器执行的默认顺序。全局过滤器围绕着类过滤器,而后者又围绕着方法过滤器。

由于过滤器嵌套,过滤器的后代码以与**前代码相反的顺序运行。过滤顺序:

以下示例说明了过滤器方法为同步操作过滤器运行的顺序:

序列 Filter scope Filter method
1 Global OnActionExecuting
2 Controller OnActionExecuting
3 Action OnActionExecuting
4 Action OnActionExecuted
5 Controller OnActionExecuted
6 Global OnActionExecuted

可以通过实现IOrderedFilter来覆盖默认的执行顺序。IOrderedFilter公开Order属性,该属性优先于范围以确定执行顺序。具有较低Order值的过滤器:

  • 在具有较高值的过滤器之前运行之前Order的代码。

  • 在具有更高值的过滤器之后运行after代码。Order

控制器级别过滤器示例中,GlobalSampleActionFilter具有全局范围,因此它在SampleActionFilterAttribute具有控制器范围之前运行。要先运行,请将SampleActionFilterAttribute其顺序设置为int.MinValue

 [SampleActionFilter(Order = int.MinValue)]
 public class ControllerFiltersController : Controller
 {
     // ...
 }

GlobalSampleActionFilter要首先运行全局过滤器,请将其设置Orderint.MinValue

 builder.Services.AddControllersWithViews(options =>
 {
     options.Filters.Add<GlobalSampleActionFilter>(int.MinValue);
 });

顺序总结:(这个指的是同一级别的Filter)

order值越小越先执行,由于是before action after 所以越小的after越后执行,和中间件类似

能用中间件实现的功能,优先考虑中间件,如果在Mvc里面的需求再考虑Filter

原文地址:https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.filters.iorderedfilter.order?view=aspnetcore-6.0#microsoft-aspnetcore-mvc-filters-iorderedfilter-order

取消和短路

可以通过在提供给过滤器方法的ResourceExecutingContext参数上设置Result属性来短路过滤器管道。例如,以下资源过滤器会阻止管道的其余部分执行:

 public class ShortCircuitingResourceFilterAttribute : Attribute, IResourceFilter
 {
     public void OnResourceExecuting(ResourceExecutingContext context)
    {
     //设置Result属性即可使ResourceFilter 之后的过滤器都不执行 在这里短路了
         context.Result = new ContentResult
        {
             Content = nameof(ShortCircuitingResourceFilterAttribute)
        };
    }
 ​
     public void OnResourceExecuted(ResourceExecutedContext context) { }
 }

在下面的代码中,[ShortCircuitingResourceFilter][ResponseHeader]filter 都以Indexaction 方法为目标。ShortCircuitingResourceFilterAttribute过滤器:

  • 首先运行,因为它是资源过滤器并且ResponseHeaderAttribute是操作过滤器。

  • 使管道的其余部分短路。

因此ResponseHeaderAttribute过滤器永远不会运行该Index操作。如果两个过滤器都在操作方法级别应用,则此行为将是相同的,前提是ShortCircuitingResourceFilterAttribute先运行。首先ShortCircuitingResourceFilterAttribute运行是因为它的过滤器类型:

 [ResponseHeader("Filter-Header", "Filter Value")]
 public class ShortCircuitingController : Controller
 {
    [ShortCircuitingResourceFilter]
     public IActionResult Index() =>
         Content($"- {nameof(ShortCircuitingController)}.{nameof(Index)}");
 }

依赖注入

过滤器可以按类型或实例添加。如果添加了一个实例,则该实例将用于每个请求。如果添加了类型,则它是类型激活的。类型激活过滤器意味着:

作为属性实现并直接添加到控制器类或操作方法的过滤器不能具有依赖注入(DI) 提供的构造函数依赖项。构造函数依赖项不能由 DI 提供,因为属性必须在应用它们的地方提供其构造函数参数。

以下过滤器支持 DI 提供的构造函数依赖项:

前面的过滤器可以应用于控制器或动作。

记录仪可从 DI 获得。但是,请避免纯粹出于日志记录目的而创建和使用过滤器。内置框架日志记录通常提供日志记录所需的内容。日志添加到过滤器:

  • 应该关注特定于过滤器的业务领域问题或行为。

  • 不应记录操作或其他框架事件。内置过滤器已经记录了操作和框架事件。

服务过滤器属性(ServiceFilterAttribute)

服务过滤器实现类型注册在Program.cs. ServiceFilterAttribute从 DI 检索过滤器的实例。

以下代码显示了LoggingResponseHeaderFilterService使用 DI 的类:

 public class LoggingResponseHeaderFilterService : IResultFilter
 {
     private readonly ILogger _logger;
 ​
     public LoggingResponseHeaderFilterService(
             ILogger<LoggingResponseHeaderFilterService> logger) =>
         _logger = logger;
 ​
     public void OnResultExecuting(ResultExecutingContext context)
    {
         _logger.LogInformation(
             $"- {nameof(LoggingResponseHeaderFilterService)}.{nameof(OnResultExecuting)}");
 ​
         context.HttpContext.Response.Headers.Add(
             nameof(OnResultExecuting), nameof(LoggingResponseHeaderFilterService));
    }
 ​
     public void OnResultExecuted(ResultExecutedContext context)
    {
         _logger.LogInformation(
             $"- {nameof(LoggingResponseHeaderFilterService)}.{nameof(OnResultExecuted)}");
    }
 }

在以下代码中,LoggingResponseHeaderFilterService添加到 DI 容器中:

 builder.Services.AddScoped<LoggingResponseHeaderFilterService>();

在以下代码中,属性从 DIServiceFilter检索过滤器的实例:LoggingResponseHeaderFilterService

 [ServiceFilter(typeof(LoggingResponseHeaderFilterService))]
 public IActionResult WithServiceFilter() =>
     Content($"- {nameof(FilterDependenciesController)}.{nameof(WithServiceFilter)}");

使用时ServiceFilterAttribute,设置ServiceFilterAttribute.IsReusable

  • 提供过滤器实例可以在创建它的请求范围之外重用的提示。ASP.NET Core 运行时不保证:

    • 将创建过滤器的单个实例。

    • 稍后将不会从 DI 容器重新请求过滤器。

  • 不应与依赖于生命周期而非单例的服务的过滤器一起使用。

ServiceFilterAttribute实现IFilterFactoryIFilterFactory公开用于创建IFilterMetadata实例的CreateInstance方法。从 DI 加载指定的类型。CreateInstance

总结

在要使用的地方如上述加上[ServiceFilter(typeof(LoggingResponseHeaderFilterService))]即可

执行结果:

类型过滤器属性(TypeFilterAttribute)

TypeFilterAttribute类似于ServiceFilterAttribute,但它的类型不是直接从 DI 容器解析的。它使用Microsoft.Extensions.DependencyInjection.ObjectFactory实例化类型。

因为TypeFilterAttribute类型不是直接从 DI 容器中解析的:

  • 使用 引用的类型TypeFilterAttribute不需要在 DI 容器中注册。它们的依赖项确实由 DI 容器实现。

  • TypeFilterAttribute可以选择接受该类型的构造函数参数。

使用时TypeFilterAttribute,设置TypeFilterAttribute.IsReusable

  • 提供过滤器实例可以在创建它的请求范围之外重用的提示。ASP.NET Core 运行时不保证将创建过滤器的单个实例。

  • 不应与依赖于生命周期而非单例的服务的过滤器一起使用。

    Filter:
     using Microsoft.AspNetCore.Mvc.Filters;
     ​
     namespace FilterMvc.Filters
     {
         public class LoggingResponseHeaderFilter : IActionFilter
        {
             private readonly string _name;
             private readonly string _value;
     ​
             public LoggingResponseHeaderFilter(string name, string value) =>
                (_name, _value) = (name, value);
     ​
             public void OnActionExecuted(ActionExecutedContext context)
            {
                 Console.WriteLine("=============方法执行后===========");
            }
     ​
             public void OnActionExecuting(ActionExecutingContext context)
            {
                 Console.WriteLine("=============方法执行前===========");
                 context.HttpContext.Response.Headers.Add(_name, _value);
            }
        }
     }

以下示例显示了如何使用 将参数传递给类型TypeFilterAttribute

 [TypeFilter(typeof(LoggingResponseHeaderFilter),
     Arguments = new object[] { "Filter-Header", "Filter Value" })]
 public IActionResult WithTypeFilter() =>
     Content($"- {nameof(FilterDependenciesController)}.{nameof(WithTypeFilter)}");

执行结果:

过滤器工厂(IFilterFactory)

IFilterFactory实现IFilterMetadata。因此,IFilterFactory实例可以用作IFilterMetadata过滤器管道中任何位置的实例。当运行时准备调用过滤器时,它会尝试将其转换为IFilterFactory. 如果该转换成功,则调用CreateInstance方法来创建所IFilterMetadata调用的实例。这提供了一种灵活的设计,因为在应用程序启动时不需要明确设置精确的过滤器管道。

IFilterFactory.IsReusable

  • 工厂提示工厂创建的过滤器实例可以在创建它的请求范围之外重用。

  • 不应与依赖于生命周期而非单例的服务的过滤器一起使用

ASP.NET Core 运行时不保证:

  • 将创建过滤器的单个实例。

  • 稍后将不会从 DI 容器重新请求过滤器。

警告

仅当过滤器的来源明确、过滤器是无状态的并且过滤器可以安全地跨多个 HTTP 请求使用时,才将IFilterFactory.IsReusable配置为返回。例如,如果返回true,则不要从注册为作用域或瞬态的 DI 中返回过滤器。IFilterFactory.IsReusable``true

IFilterFactory可以使用自定义属性实现作为创建过滤器的另一种方法来实现:

 public class ResponseHeaderFilterFactory : Attribute, IFilterFactory
 {
     public bool IsReusable => false;
 ​
     public IFilterMetadata CreateInstance(IServiceProvider serviceProvider) =>
         new InternalResponseHeaderFilter();
 ​
     private class InternalResponseHeaderFilter : IActionFilter
    {
         public void OnActionExecuting(ActionExecutingContext context) =>
             context.HttpContext.Response.Headers.Add(
                 nameof(OnActionExecuting), nameof(InternalResponseHeaderFilter));
 ​
         public void OnActionExecuted(ActionExecutedContext context) { }
    }

过滤器应用在以下代码中:

 [ResponseHeaderFilterFactory]
 public IActionResult Index() =>
     Content($"- {nameof(FilterFactoryController)}.{nameof(Index)}");

总结:

IFilterFactory.IsReusable(可复用) 这个属性直接关系到生命周期以及使用场景。根据自己具体项目来看

True则时单例,不能与非单例的Filter一起使用。

IFilterFactory 在属性(Attribute)上实现

实现IFilterFactory的过滤器对于以下过滤器很有用:

  • 不需要传递参数。

  • 具有需要由 DI 填充的构造函数依赖项。

TypeFilterAttribute实现IFilterFactoryIFilterFactory公开用于创建IFilterMetadata实例的CreateInstance方法。从服务容器 (DI) 加载指定的类型。CreateInstance

 public class SampleActionTypeFilterAttribute : TypeFilterAttribute
 {
     public SampleActionTypeFilterAttribute()
          : base(typeof(InternalSampleActionFilter)) { }
 ​
     private class InternalSampleActionFilter : IActionFilter
    {
         private readonly ILogger<InternalSampleActionFilter> _logger;
 ​
         public InternalSampleActionFilter(ILogger<InternalSampleActionFilter> logger) =>
             _logger = logger;
 ​
         public void OnActionExecuting(ActionExecutingContext context)
        {
             _logger.LogInformation(
                 $"- {nameof(InternalSampleActionFilter)}.{nameof(OnActionExecuting)}");
        }
 ​
         public void OnActionExecuted(ActionExecutedContext context)
        {
             _logger.LogInformation(
                 $"- {nameof(InternalSampleActionFilter)}.{nameof(OnActionExecuted)}");
        }
    }
 }

以下代码显示了三种应用过滤器的方法:

 [SampleActionTypeFilter]//推荐使用这种
 public IActionResult WithDirectAttribute() =>
     Content($"- {nameof(FilterFactoryController)}.{nameof(WithDirectAttribute)}");
 ​
 [TypeFilter(typeof(SampleActionTypeFilterAttribute))]
 public IActionResult WithTypeFilterAttribute() =>
     Content($"- {nameof(FilterFactoryController)}.{nameof(WithTypeFilterAttribute)}");
 ​
 [ServiceFilter(typeof(SampleActionTypeFilterAttribute))]
 public IActionResult WithServiceFilterAttribute() =>
     Content($"- {nameof(FilterFactoryController)}.{nameof(WithServiceFilterAttribute)}");

在前面的代码中,首选应用过滤器的第一种方法。

在过滤器管道中使用中间件

资源过滤器像中间件一样工作,因为它们围绕管道中稍后出现的所有内容的执行。但是过滤器与中间件的不同之处在于它们是运行时的一部分,这意味着它们可以访问上下文和构造。

要将中间件用作过滤器,请使用Configure指定要注入过滤器管道的中间件的方法创建一个类型。以下示例使用中间件设置响应标头:

 public class FilterMiddlewarePipeline
 {
     public void Configure(IApplicationBuilder app)
    {
         app.Use(async (context, next) =>
        {
             context.Response.Headers.Add("Pipeline", "Middleware");
 ​
             await next();
        });
    }
 }

使用MiddlewareFilterAttribute运行中间件:

 [MiddlewareFilter(typeof(FilterMiddlewarePipeline))]//MiddlewareFilter
 public class FilterMiddlewareController : Controller
 {
     public IActionResult Index() =>
         Content($"- {nameof(FilterMiddlewareController)}.{nameof(Index)}");
 }

中间件过滤器与资源过滤器在过滤器管道的同一阶段运行,在模型绑定之前和管道的其余部分之后。

执行结果

线程安全

When passing an instance of a filter into Add, instead of its Type, the filter is a singleton and is not thread-safe.

当将过滤器的实例Add传递给而不是其Type时,过滤器是单例并且不是线程安全的。(机翻)

例子: T t = new T();

Add(t);

授权过滤器

授权过滤器:

  • 第一个过滤器是否在过滤器管道中运行。

  • 控制对操作方法的访问。

  • 有 before 方法,但没有 after 方法。

自定义授权过滤器需要自定义授权框架。优先配置授权策略或编写自定义授权策略而不是编写自定义过滤器。内置授权过滤器:

  • 调用授权系统。

  • 不授权请求。

不要在授权过滤器中抛出异常

  • 将不处理异常。

  • 异常过滤器不会处理异常。

考虑在授权过滤器中发生异常时发出质询。

了解有关授权的更多信息。

资源过滤器

资源过滤器:

资源过滤器可用于使大部分管道短路。例如,缓存过滤器可以避免缓存命中的其余管道。

资源过滤器示例:

动作过滤器

操作过滤器不适用于 Razor 页面。Razor Pages 支持IPageFilterIAsyncPageFilter。有关详细信息,请参阅Razor 页面的筛选方法

动作过滤器:

以下代码显示了一个示例操作过滤器:

 public class SampleActionFilter : IActionFilter
 {
     public void OnActionExecuting(ActionExecutingContext context)
    {
         // Do something before the action executes.
    }
 ​
     public void OnActionExecuted(ActionExecutedContext context)
    {
         // Do something after the action executes.
    }
 }

ActionExecutingContext提供以下属性:

  • ActionArguments - 允许读取操作方法的输入。

  • 控制器- 启用操纵控制器实例。

  • 结果- 设置Result短路执行操作方法和后续操作过滤器。

在操作方法中抛出异常:

  • 防止运行后续过滤器。

  • 与设置不同Result,被视为失败而不是成功的结果。

ActionExecutedContext提供Controller加上Result以下属性:

  • Canceled - 如果操作执行被另一个过滤器短路,则为真。

  • Exception

    - 如果操作或先前运行的操作过滤器引发异常,则为非 null。将此属性设置为 null:

    • 有效地处理异常。

    • Result就像从 action 方法返回一样执行。

对于一个IAsyncActionFilter,调用ActionExecutionDelegate

  • 执行任何后续操作过滤器和操作方法。

  • returnsActionExecutedContext

要短路,请将Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext.Result分配给结果实例并且不要调用next( ActionExecutionDelegate)。

该框架提供了一个可以被子类化的抽象ActionFilterAttribute 。

动作过滤器OnActionExecuting可用于:

  • 验证模型状态。

  • 如果状态无效,则返回错误。

public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(context.ModelState);
}
}
}

[ApiController]使用该属性注释的控制器会自动验证模型状态并返回 400 响应。有关详细信息,请参阅自动 HTTP 400 响应

OnActionExecuted方法在操作方法之后运行:

  • 并且可以通过Result属性查看和操作动作的结果。

  • 如果操作执行被另一个过滤器短路,则Canceled设置为 true。

  • 如果操作或后续操作过滤器引发异常,则将Exception设置为非空值。设置Exception为空:

    • 有效地处理异常。

    • ActionExecutedContext.Result就像从 action 方法正常返回一样执行。

异常过滤器

异常过滤器:

以下示例异常筛选器显示有关在开发应用程序时发生的异常的详细信息:

public class SampleExceptionFilter : IExceptionFilter
{
private readonly IHostEnvironment _hostEnvironment; public SampleExceptionFilter(IHostEnvironment hostEnvironment) =>
_hostEnvironment = hostEnvironment; public void OnException(ExceptionContext context)
{
if (!_hostEnvironment.IsDevelopment())
{
// Don't display exception details unless running in Development.
return;
} context.Result = new ContentResult
{
Content = context.Exception.ToString()
};
}
}

以下代码测试异常过滤器:

 [TypeFilter(typeof(SampleExceptionFilter))]
 public class ExceptionController : Controller
 {
     public IActionResult Index() =>
         Content($"- {nameof(ExceptionController)}.{nameof(Index)}");
 }

异常过滤器:

要处理异常,请将ExceptionHandled属性设置为true或分配Result属性。这会阻止异常的传播。异常过滤器不能将异常转化为“成功”。只有动作过滤器可以做到这一点。

异常过滤器:

  • 适用于捕获动作中发生的异常。

  • 不如错误处理中间件灵活。

首选中间件进行异常处理。仅在错误处理因调用的操作方法而异时才使用异常过滤器。例如,一个应用程序可能具有 API 端点和视图/HTML 的操作方法。API 端点可以以 JSON 形式返回错误信息,而基于视图的操作可以以 HTML 形式返回错误页面。

结果过滤器

结果过滤器:

IResultFilter 和 IAsyncResultFilter

以下代码显示了一个示例结果过滤器:

 public class SampleResultFilter : IResultFilter
 {
     public void OnResultExecuting(ResultExecutingContext context)
    {
         // Do something before the result executes.
    }
 ​
     public void OnResultExecuted(ResultExecutedContext context)
    {
         // Do something after the result executes.
    }
 }

执行的结果类型取决于操作。返回视图的操作包括所有 razor 处理作为正在执行的ViewResult的一部分。作为结果执行的一部分,API 方法可能会执行一些序列化。了解有关行动结果的更多信息。

结果过滤器仅在操作或操作过滤器产生操作结果时执行。在以下情况下不执行结果过滤器:

  • 授权过滤器或资源过滤器使管道短路。

  • 异常过滤器通过生成操作结果来处理异常。

Microsoft.AspNetCore.Mvc.Filters.IResultFilter.OnResultExecuting方法可以通过将Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext.Cancel设置为来短路操作结果和后续结果筛选器的执行true。短路时写入响应对象以避免生成空响应。抛出异常IResultFilter.OnResultExecuting

  • 阻止执行操作结果和后续过滤器。

  • 被视为失败而不是成功的结果。

Microsoft.AspNetCore.Mvc.Filters.IResultFilter.OnResultExecuted方法运行时,响应可能已经发送到客户端。如果响应已经发送到客户端,则无法更改。

ResultExecutedContext.Canceled``true如果动作结果执行被另一个过滤器短路,则设置为。

ResultExecutedContext.Exception如果操作结果或后续结果过滤器抛出异常,则设置为非空值。设置Exception为 null 可以有效地处理异常并防止在管道中稍后再次抛出异常。在结果过滤器中处理异常时,没有可靠的方法将数据写入响应。如果在操作结果引发异常时已将标头刷新到客户端,则没有可靠的机制来发送失败代码。

对于IAsyncResultFilterawait next ,对ResultExecutionDelegate的调用将执行任何后续结果过滤器和操作结果。要短路,请将ResultExecutingContext.Cancel设置为true并且不要调用ResultExecutionDelegate

 public class SampleAsyncResultFilter : IAsyncResultFilter
 {
     public async Task OnResultExecutionAsync(
         ResultExecutingContext context, ResultExecutionDelegate next)
    {
         if (context.Result is not EmptyResult)
        {
             await next();
        }
         else
        {
             context.Cancel = true;
        }
    }
 }

ResultFilterAttribute该框架提供了一个可以被子类化的抽象。前面显示的ResponseHeaderAttribute类是结果过滤器属性的一个示例。

IAlwaysRunResultFilter 和 IAsyncAlwaysRunResultFilter

IAlwaysRunResultFilter和IAsyncAlwaysRunResultFilter接口声明了一个针对所有操作结果运行的IResultFilter实现。这包括由以下人员产生的行动结果:

  • 短路的授权过滤器和资源过滤器。

  • 异常过滤器。

例如,当内容协商失败时,以下过滤器始终运行并设置带有422 Unprocessable Entity状态代码的操作结果 ( ObjectResult ):

 public class UnprocessableResultFilter : IAlwaysRunResultFilter
 {
     public void OnResultExecuting(ResultExecutingContext context)
    {
         if (context.Result is StatusCodeResult statusCodeResult
             && statusCodeResult.StatusCode == StatusCodes.Status415UnsupportedMediaType)
        {
             context.Result = new ObjectResult("Unprocessable")
            {
                 StatusCode = StatusCodes.Status422UnprocessableEntity
            };
        }
    }
 ​
     public void OnResultExecuted(ResultExecutedContext context) { }
 }

以下是图片

Filters in ASP.NET Core(Net6之过滤器)的更多相关文章

  1. Filters in ASP.NET Core (转自MSDN)

    Filters in ASP.NET Core MVC allow you to run code before or after specific stages in the request pro ...

  2. Filters in ASP.NET Core

    Filters in ASP.NET Core allow code to be run before or after specific stages in the request processi ...

  3. ASP.NET Core MVC 之过滤器(Filter)

    ASP.NET MVC 中的过滤器允许在执行管道中的特定阶段之前或之后运行代码.可以对全局,也可以对每个控制器或每个操作配置过滤器. 1.过滤器如何工作 不同的过滤器类型在管道中的不同阶段执行,因此具 ...

  4. Asp.Net Core中利用过滤器控制Nginx的缓存时间

    前言 Web项目中很多网页资源比如html.js.css通常会做服务器端的缓存,加快网页的加载速度 一些周期性变化的API数据也可以做缓存,例如广告资源位数据,菜单数据,商品类目数据,商品详情数据,商 ...

  5. ASP.NET core MVC动作过滤器执行顺序

    using Microsoft.AspNetCore.Mvc.Filters; using System; using System.Threading.Tasks; namespace dotnet ...

  6. asp.net core的授权过滤器中获取action上的Attribute

    var action = context.ActionDescriptor as ControllerActionDescriptor; var permission = action.MethodI ...

  7. asp.net core 2.2 中的过滤器/筛选器(上)

    ASP.NET Core中的过滤器/筛选器 通过使用 ASP.NET Core MVC 中的筛选器,可在请求处理管道中的特定阶段之前或之后运行代码. 注意:本主题不适用于 Razor 页面. ASP. ...

  8. Asp.net Core过滤器

    Asp.net Core五类过滤器:Authorization Filter.Resource Filter.Acton Filter.Exception Filter.Result Filter.优 ...

  9. Asp.Net Core 轻松学-被低估的过滤器

    前言     过滤器,从我们开始开发 Asp.Net 应用程序开始,就一直伴随在我们左右:Asp.Net Core 提供多种类型的过滤器,以满足多种多样的业务应用场景:并且在 Asp.Net Core ...

  10. 用ASP.NET Core 2.0 建立规范的 REST API

    什么是REST REST 是 Representational State Transfer 的缩写. 它是一种架构的风格, 这种风格基于一套预定义的规则, 这些规则描述了网络资源是如何定义和寻址的. ...

随机推荐

  1. Asp-Net-Core-搭建ELK日志平台-Docker-Compose版本

    title: Asp.Net Core 搭建ELK日志平台(Docker-Compose版本) date: 2022-09-27 15:16:59 tags: - .NET 由于暂时用不上Logsta ...

  2. [cocos2d-x]关于3.x的触摸机制

    触摸机制的概念 通过对要监听触摸的节点进行注册,然后自定义相应的触摸函数,由事件监听器实现对触摸的监听并且实现相应的响应动作. 触摸的分类 单点触摸 下面是实现单点触摸监听的步骤: //第一步:先创建 ...

  3. liunx系统安装JDK环境详细步骤

    Liunx系统安装JDK环境详细步骤 一 下载liunx版本jdk压缩包 进入JDK官方网站下载jdk压缩包.下载前需要登入账户,可以自己注册一个账户! 也可以使用本博主提供的网盘下载https:// ...

  4. 经典问题 1 —— DAG 上区间限制拓扑序

    问题描述 给定一个 DAG,求一个拓扑序,使得节点 \(i\) 的拓扑序 \(\in [l_i,r_i]\). 题解 首先进行一个预处理:对于所有 \(u\),令 \(\forall (v,u)\in ...

  5. QtQuick使用MediaPlayer抓取摄像头影响报错Error: "Your GStreamer installation is missing a plug-in."

    环境:ubuntu18.04 Qt5.9.5 描述:项目需要使用qtquick作为显示界面用于播放从网络摄像头抓取的影像,海康网络摄像头,摄像头源协议使用的是rtsp,影像数据格式为x-h264,但在 ...

  6. 【学习笔记】C/C++ 设计模式 - 观察者模式

    前言 估计 2020 年写应用程序的机会比较多,之前一直在做嵌入式驱动程序和Android系统定制方面的工作,在应用程序方面积累的不是很多,因此迫切需要多学学应用编程这方面的知识. 之前在写小的应用程 ...

  7. 转载:SQL分页查询总结

    [转载]SQL分页查询总结 开发过程中经常遇到分页的需求,今天在此总结一下吧.    简单说来方法有两种,一种在源上控制,一种在端上控制.源上控制把分页逻辑放在SQL层:端上控制一次性获取所有数据,把 ...

  8. 亲测有效! Scrutiny 网站SEO检测及优化工具 V12.6.1 for mac

    亲测有效! Scrutiny 网站SEO检测及优化工具  V12.6.1 for mac Scrutiny是一款网站SEO工具,它能够自动检测目标网站的坏链.HTML验证.描述Description. ...

  9. 【已解决】将jsp文件在浏览器打开直接出现代码,在浏览器出现本地地址,tomcat报错

    问题背景: 导入了一个项目直接打开可以,但是想跟一遍代码,把配置文件全部整理成为一个springmvc的基础配置文件 跟着配置到自己tomcat就不管怎样都是下面的截图  希望可以帮到一起报错的朋友快 ...

  10. Docker中Mysql容器忘记密码的处理方法

    今天非常的倒霉,因为学习了Vue的相关知识,想自己写一个后端服务器来练习一下Vue 然后 忘记了Docker中Mysql的密码... 很抽象 下面是我的解决方法 一.如果在本地的Navicat Pre ...