skip to Main Content

I have an asp. Net Core WebAPI application, I have created a generic custom base controller class that already provides CRUD operations (GetAll, GetById, Insert, Update and Delete) for any controller that’s being inherited from.

In some of my controllers, I have to disable some methods. Of course I could use the [nonaction] attribute to do so.

Is it possible to implement an attribute and apply it on my controller to disable a series on methods?

Here is a bit of my code:

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);
}

and my custom base controller is like this:

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);
    }
}

2

Answers


  1. Chosen as BEST ANSWER

    Thanks guys by the way! I actually found the right implementation

    1. Define a custom attribute

      [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
      public class DisableBaseOperationsAttribute : Attribute
      {
      
      }
      
    2. Then I implemented the IControllerModelConvention interface like below:

    public class ProcessMiningControllerModelConvention : IControllerModelConvention
    {
        private List<string> baseOperations;
        public void Apply(ControllerModel controller)
        {
            baseOperations = new List<string>()
            {
                "GetAll",
                "GetById",
                "Insert",
                "Update",
                "Delete",
            };
            bool disableCrud = controller.Attributes.Any(a => a.GetType() == typeof(DisableBaseOperationsAttribute));
            if (disableCrud)
            {
                var crudActions = controller.Actions.Where(a => baseOperations.Contains(a.ActionName));
                foreach (var action in crudActions)
                {
                    action.ApiExplorer.IsVisible = false;
                }
            }
        }
    
    }
    
    
    1. And finally config AddControllers like:

      builder.Services.AddControllers(s => s.Conventions.Add(new ProcessMiningControllerModelConvention()));
      
      
      
    2. Now you could easily use the attribute on your controller to disable base operations


  2. You can disable a controller with its action in four steps:

    1- Create an action filter attribute to make the controller always return 404 NOT Found like the code below:

        public class DisableControllerAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            filterContext.Result = new NotFoundObjectResult(null);
        }
    }
    

    2- Register the filter in the application Program.cs like this:

    builder.Services.AddControllers((c) => c.Filters.Add<DisableControllerAttribute>());
    

    3- Decorate the controller with the action filter you have created:

    [DisableController]
    public class ValuesController : ControllerBase
    

    4- This step is optional. If you want to hide the controller from Swagger page also add the following attribute to the controller

    [ApiExplorerSettings(IgnoreApi = true)]
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search