仅将操作过滤器添加到 [ApiController] 注释控制器的操作?

Posted

技术标签:

【中文标题】仅将操作过滤器添加到 [ApiController] 注释控制器的操作?【英文标题】:Add action filter to [ApiController] annotated controller's actions only? 【发布时间】:2021-12-16 11:28:17 【问题描述】:

在 Core 之前,当 MVC 和 Web API 的控制器是分开的时,很容易在一个框架或另一个框架上定位一个全局操作。现在有了mvcOptions.Filters.Add<T>();,它将应用于您的 MVC 视图呈现操作,而您只是 API 操作。

我可以粗略地看到,当您使用 [ApiController] (docs) 时,您选择了几种约定/行为,但目前尚不清楚如何/是否可以轻松添加到该约定中。可能我需要创建自己的额外ApiBehaviorApplicationModelProvider,比如here?我正在寻找更简单的东西,比如mvcOptions.ApiConvention.Filters.Add(x)

另一种方法是让我的所有 API 控制器继承我自己的 ApiControllerBase 并对其进行注释,但如果可能的话,我更愿意扩展约定。

不用MvcControllerBase 也可以换一种方式来查看。

【问题讨论】:

【参考方案1】:

据我所知,[ApiController] 约定没有内置的可扩展性,但您可以使用application model 实现您想要的。

这是一个 IControllerModelConvention 的示例实现,它查找 [ApiController] 属性,您可以填写您的具体实现:

public class ExampleControllerModelConvention : IControllerModelConvention

    public void Apply(ControllerModel controllerModel)
    
        if (controllerModel.Attributes.OfType<ApiControllerAttribute>().Any())
        
            // ...
        
    

您可以在 Startup.ConfigureServicesProgram.cs 中为 .NET 6+ 注册此约定:

// Startup.ConfigureServices
services.AddControllers(options =>

    options.Conventions.Add(new SampleControllerModelConvention());
);
// Program.cs
builder.Services.AddControllers(options =>

    options.Conventions.Add(new SampleControllerModelConvention());
);

您链接到的ApiBehaviorApplicationModelProvider 类中的IsApiController 方法处理检查的方式略有不同:

private static bool IsApiController(ControllerModel controller)

    if (controller.Attributes.OfType<IApiBehaviorMetadata>().Any())
    
        return true;
    

    var controllerAssembly = controller.ControllerType.Assembly;
    var assemblyAttributes = controllerAssembly.GetCustomAttributes();
    return assemblyAttributes.OfType<IApiBehaviorMetadata>().Any();

此实现支持将[ApiController] 属性应用于控制器所在的程序集。如果您还使用视图,则可能不需要此属性,但值得注意的是这种方法的区别。

【讨论】:

以上是关于仅将操作过滤器添加到 [ApiController] 注释控制器的操作?的主要内容,如果未能解决你的问题,请参考以下文章

按月过滤的 VBA 宏,仅将当月的数据粘贴到不同的工作表上

尽管端点在 apicontroller 内部的行为中使用了 cors 类,但 CORS 标头未添加到响应中

在 ApiController 中添加自定义响应头

iOS 仅将某些推送通知过滤为徽章

JQuery 仅将选中的行添加到数组

F# - 依赖管理