【问题标题】:Custom action filter (with dependencies) not working in ASP.NET Core 3.1 Web API自定义操作过滤器(带有依赖项)在 ASP.NET Core 3.1 Web API 中不起作用
【发布时间】:2021-01-01 19:11:21
【问题描述】:

我在让自定义操作过滤器在 ASP.NET Core 3.1 Web API 中工作时遇到了一些困难。我关注了this SO,以及Microsoft docs,但它不起作用。我创建了一个简单的过滤器(注意:我需要依赖注入);

public class LogFilterAttribute : ActionFilterAttribute, IFilterMetadata
{
    private readonly ILogger<LogFilterAttribute> _logger;

    public LogFilterAttribute(ILogger<LogFilterAttribute> logger)
    {
        _logger = logger;
    }

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        _logger.LogWarning("test");
        base.OnActionExecuting(actionContext);
    }
}

注意事项:

  • ActionFilterAttribute 来自 System.Web.Http.Filters 命名空间。

  • 我实现了IFilterMetadata(这只是一个标记接口),因为ServiceFilterTypeFilter 似乎需要这样做。

我在Startup.csConfigureServices 中注册,如下所示:

services.AddScoped<LogFilterAttribute>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

然后将其应用到我的 Web API 控制器中,如下所示:

[ApiVersion("1.0")]
[ApiController]
[Route("v{version:apiVersion}/resources/{id}")]
public class ResourceController : ControllerBase
{
   private readonly ILogger<ResourceController> _logger;

   public ResourceController(ILogger<ResourceController> logger)
   {
      _logger = logger;
   }

   [HttpGet]
   [ServiceFilter(typeof(LogFilterAttribute))]
   public async Task<IActionResult> Get([FromRoute(Name = "id")] string id)
   {
      _logger.LogInformation($"{typeof(ResourceController)}.{nameof(Get)}");
      return Ok();
   }
}

我已经尝试过ServiceFilterTypeFilter,但无济于事 - 它只是跳过过滤器中的断点并直接进入我的路由逻辑。我做错了什么?

【问题讨论】:

    标签: asp.net-web-api action-filter


    【解决方案1】:

    尝试用 IActionFilter 代替 ActionFilterAttribute

    【讨论】:

    • 谢谢 - 这对我有点帮助 - 实现了 IAsyncActionFilter 并覆盖了 Attribute
    【解决方案2】:

    在 StartUp.cs 中,在 MVC 管道中添加过滤器。

       public void ConfigureServices(IServiceCollection services)
       {
            services.AddMvc(options =>
                        {
                            options.Filters.Add(typeof(LogFilterAttribute));
                        });
       }
    

    【讨论】:

      【解决方案3】:

      当您使用类型过滤器时,您需要在控制器/方法上使用它,记录器不是已经在配置范围内吗?如果是这样,您需要一个类型过滤器

      [TypeFilter(typeof(LogFilterAttribute))]
      

      为了我的使用,我不需要添加 IFilterMetadata

      【讨论】:

        【解决方案4】:

        最后我通过实现IAsyncActionFilter 并从Attribute 继承解决了这个问题,如下所示:

        public class LogFilterActionFilterAttribute : Attribute, IAsyncActionFilter
        {
           public LogFilterActionFilterAttribute(...)
           {
              ...
           }
        
           public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
           {
              ...
           }
        }
        

        我还覆盖TypeFilterAttribute,如下所示:

           public class LogFilterAttribute : TypeFilterAttribute
           {
              public LogFilterAttribute (...) : base(typeof(LogFilterActionFilterAttribute))
              {
                 Arguments = new object[] { ... };
              }
           }
        

        这样我就可以在控制器/路由上进行如下装饰:

        [ApiVersion("1.0")]
        [ApiController]
        [Route("v{version:apiVersion}/resources/{id}")]
        public class ResourceController : ControllerBase
        {
           private readonly ILogger<ResourceController> _logger;
        
           public ResourceController(ILogger<ResourceController> logger)
           {
              _logger = logger;
           }
        
           [HttpGet]
           [LogFilter(...)]
           public async Task<IActionResult> Get([FromRoute(Name = "id")] string id)
           {
              _logger.LogInformation($"{typeof(ResourceController)}.{nameof(Get)}");
              return Ok();
           }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多