asp.netasp.net-mvc.net-coreactionfilterattributecustom-action-filter

Action filter : how to call service layer and async method


I have a controller with many action method. The requirement for me is to check a value of a field from database and if the field value is "true" all the action methods can execute otherwise these action methods should not execute. The method is in service layer

public class CustomAttributeFilter : ActionFilterAttribute
{
    public  override void  OnActionExecuting(ActionExecutingContext filterContext)
    {
        var myFlag = await _adminDB.GetFlagSettingsAsync();
        
        // how do i call async method from OnActionExecuting filter
        if (!myFlag)
        {
            //Create your result
            filterContext.Result = new EmptyResult();
        }
        else
        {
            base.OnActionExecuting(filterContext);
        }
    }

}

Interface implementaion

public interface IAdminDB
    {
        
        Task<MySettings> GetMySettingsAsync();
    }

public class AdminDB : IAdminDB
    {
public async Task<MySettings> GetMySettingsAsync()
        {
            var dbName = _appSettings.AdminDbName;
            var blobName = _appSettings.AdminBlobName;
            return await _dbStorage.GetBlobAsync<MySettings>(blobName, dbName);
        } 
}



public class MySettings
    {      
        public bool MyFlag { get; set; }
    }

I get an error message "no suitable method found to override". How do i clear this error and how to inject service properly . Above is what i have tried, the call to async getting failed here.


Solution

  • I don't see where the _adminDB dependency comes from in your code, but I'm guessing that is causing the problem.

    If you want to use async filters you have to implement the IAsyncActionFilter interface.

    You can retrieve services from the executing context's DI container and use async methods the following way:

     public class CustomAttributeFilter : ActionFilterAttribute
     {
         public override async Task OnActionExecutionAsync(
        ActionExecutingContext context, ActionExecutionDelegate next)
         {
             var adminDb = filterContext.HttpContext.RequestServices.GetService<AdminDb>();
             var myFlag = await adminDb.GetFlagSettingsAsync();
             
             //..
    
             await next();
         }
     }
    

    Depending on your your needs, you can place your custom logic after the next() call as well.

    See the documentation for more information.