You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现自定义C#特性禁用ASP.NET Core WebAPI控制器方法?

批量禁用ASP.NET Core WebAPI基础控制器CRUD方法的解决方案

问题背景

我有一个ASP.NET Core WebAPI应用,已实现通用基础控制器ProcessMiningControllerBase<T>,为所有继承它的控制器提供CRUD操作(GetAll、GetById、Insert、Update、Delete)。部分控制器需要禁用某些CRUD方法,虽然可以用[NonAction]特性逐个标记,但希望实现一个可应用于控制器的特性,批量指定要禁用的方法。

相关代码

基础服务接口

public interface IBaseService<T> where T : DomainObject {
    Task<PagedResultViewModel<T>> GetAllAsync(BaseRequestViewModel request);
    Task<SingleResultViewModel<T>> GetByIdAsync(int id);
    Task<SingleResultViewModel<T>> InsertAsync(T entity);
    Task<SingleResultViewModel<T>> UpdateAsync(T entity);
    Task<SingleResultViewModel<T>> DeleteAsync(int id);
}

自定义基础控制器

public class ProcessMiningControllerBase<T> : ControllerBase where T : DomainObject
{
    private readonly IBaseService<T> _baseService;

    public ProcessMiningControllerBase(IBaseService<T> baseService)
    {
        _baseService = baseService;
    }

    [HttpPost]
    public virtual async Task<PagedResultViewModel<T>> GetAllAsync(BaseRequestViewModel request)
    {
        return await _baseService.GetAllAsync(request);
    }

    [HttpGet("{id}")]
    public virtual async Task<SingleResultViewModel<T>> GetByIdAsync(int id)
    {
        return await _baseService.GetByIdAsync(id);
    }

    [HttpPost]
    public virtual async Task<SingleResultViewModel<T>> InsertAsync(T entity)
    {
        return await _baseService.InsertAsync(entity);
    }

    [HttpPut]
    public virtual async Task<SingleResultViewModel<T>> UpdateAsync(T entity)
    {
        return await _baseService.UpdateAsync(entity);
    }

    [HttpDelete("{id}")]
    public virtual async Task<SingleResultViewModel<T>> DeleteAsync(int id)
    {
        return await _baseService.DeleteAsync(id);
    }
}

实现步骤

1. 定义CRUD操作枚举

创建带[Flags]特性的枚举,用于标识要禁用的CRUD方法:

[Flags]
public enum CrudActions
{
    None = 0,
    GetAll = 1 << 0,
    GetById = 1 << 1,
    Insert = 1 << 2,
    Update = 1 << 3,
    Delete = 1 << 4,
    All = GetAll | GetById | Insert | Update | Delete
}

2. 创建控制器级禁用特性

实现可应用于控制器的自定义特性,接收要禁用的CRUD操作枚举:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class DisableCrudActionsAttribute : Attribute
{
    public CrudActions DisabledActions { get; }

    public DisableCrudActionsAttribute(CrudActions disabledActions)
    {
        DisabledActions = disabledActions;
    }
}

3. 实现约定处理逻辑

通过IActionModelConvention在API模型构建阶段,自动为指定方法添加[NonAction]特性:

public class DisableCrudActionsConvention : IActionModelConvention
{
    public void Apply(ActionModel action)
    {
        var disableAttribute = action.Controller.ControllerType.GetCustomAttribute<DisableCrudActionsAttribute>();
        if (disableAttribute == null)
            return;

        var disabledActions = disableAttribute.DisabledActions;

        // 匹配基础控制器中的方法名,添加NonAction特性
        if ((disabledActions & CrudActions.GetAll) != 0 && action.ActionName == nameof(ProcessMiningControllerBase<DomainObject>.GetAllAsync))
        {
            action.Filters.Add(new NonActionAttribute());
        }

        if ((disabledActions & CrudActions.GetById) != 0 && action.ActionName == nameof(ProcessMiningControllerBase<DomainObject>.GetByIdAsync))
        {
            action.Filters.Add(new NonActionAttribute());
        }

        if ((disabledActions & CrudActions.Insert) != 0 && action.ActionName == nameof(ProcessMiningControllerBase<DomainObject>.InsertAsync))
        {
            action.Filters.Add(new NonActionAttribute());
        }

        if ((disabledActions & CrudActions.Update) != 0 && action.ActionName == nameof(ProcessMiningControllerBase<DomainObject>.UpdateAsync))
        {
            action.Filters.Add(new NonActionAttribute());
        }

        if ((disabledActions & CrudActions.Delete) != 0 && action.ActionName == nameof(ProcessMiningControllerBase<DomainObject>.DeleteAsync))
        {
            action.Filters.Add(new NonActionAttribute());
        }
    }
}

4. 注册约定到服务

在Program.cs中添加该约定到控制器配置:

builder.Services.AddControllers(options =>
{
    options.Conventions.Add(new DisableCrudActionsConvention());
});

5. 使用示例

在需要禁用特定CRUD方法的控制器上应用特性即可,比如禁用Insert和Delete:

[DisableCrudActions(CrudActions.Insert | CrudActions.Delete)]
public class SampleController : ProcessMiningControllerBase<SampleDomainObject>
{
    public SampleController(IBaseService<SampleDomainObject> baseService) : base(baseService)
    {
    }
}

说明

  • 该方案通过约定机制批量处理,避免了在每个方法上重复标记[NonAction]
  • 方法匹配基于方法名,确保和基础控制器中的方法名称一致即可
  • 枚举使用[Flags]支持同时禁用多个操作

内容的提问来源于stack exchange,提问作者Amir Monfared

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 04:57:34