Search code examples
c#asp.net-coreasp.net-core-webapiactionfilterattribute

GetService in ActionFilterAttribute returns null


I created an action filter to check if the id is correct according to the incoming id. The constructor method of the filter takes a service type parameter.

I need service to check this id before ActionMethod runs.But GetService() method returns null.

ActionFilter

 public class ContainsFilterAttribute : ActionFilterAttribute
{
    private Type _service;
    private Type _entity;
    private IdSections _idSections;
    public ContainsFilterAttribute(Type service, Type entity, IdSections idSections)
    {
        if (!typeof(ICommonService).IsAssignableFrom(service) || !typeof(IEntity).IsAssignableFrom(entity))
        {
            throw new System.Exception("Service or entity undefined.");
        }
        _service = service;
        _entity = entity;
        _idSections = idSections;
    }
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        //returns null service
        var service = (ICommonService)context.HttpContext.RequestServices.GetService(_service);
        var entity = (IEntity)Activator.CreateInstance(_entity);
        
        if (IdSections.FromRoute == _idSections)
        {
            entity.Id = (int)context.ActionArguments.FirstOrDefault(pair => pair.Key.ToUpper().Contains("ID")).Value;
        }
        var res = service.Contains(entity);
    }
}

ActionMethod

    [HttpGet]
    [Route("{userId}/user-channels")]
    [ContainsFilter(typeof(UserManager), typeof(User), IdSections.FromRoute)]
    public IActionResult GetUserChannels(int userId)
    {
        var result = _channelService.GetUserChannels(userId);
        if (result.IsSuccessful)
        {
            var mapResult = _mapper.Map<List<ChannelForListDto>>(result.Data);
            return Ok(mapResult);
        }
        return this.ServerError(result.Message);
    }

Injection

services.AddScoped<IUserService, UserManager>();

Solution

  • IUserService is registered as the service

    services.AddScoped<IUserService, UserManager>();
    

    but you are trying to resolve the implementation UserManager in the shown attribute

     [ContainsFilter(typeof(UserManager), typeof(User), IdSections.FromRoute)]
    

    call

    [ContainsFilter(typeof(IUserManager), typeof(User), IdSections.FromRoute)] 
    

    instead