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

Add action filter to [ApiController] annotated controller's actions only?

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

我可以粗略地看到当你使用 [ApiController] 时(docs), you're opted in to several conventions/behaviours, but it's not super clear how/if I could add to that convention easily. Potentially I need to create my own additional ApiBehaviorApplicationModelProvider, like the one here?我正在寻找更简单的东西,比如 mvcOptions.ApiConvention.Filters.Add(x)

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

如果不需要 MvcControllerBase 来获得观看效果,那么换个方向也不错。

据我所知,[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 class 中的 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] 属性应用于控制器所在的程序集。如果您还使用视图,则可能不需要它,但值得注意此方法的区别。