简体   繁体   中英

Dependency injection inside a FilterAttribute in ASP.NET MVC 6

I'm struggling with ASP.NET MVC 6 (beta 4 release) trying to inject a service within a controller filter attribute of type AuthorizationFilterAttribute .

This is the service (it has another service injected)

public class UsersTableRepository
{
    private readonly NeurosgarContext _dbContext;

    public UsersTableRepository(NeurosgarContext DbContext)
    {
        _dbContext = DbContext;
    }

    public ICollection<User> AllUsers
    {
        get
        {
            return _dbContext.Users.ToList();
        }
    }

    //other stuff...
}

This is the ConfigureServices method in Startup class for services enabling

  public void ConfigureServices(IServiceCollection services)
  {
        //...

        services.AddSingleton<NeurosgarContext>(a => NeurosgarContextFactory.GetContext());
        services.AddSingleton<UifTableRepository<Nazione>>();
        services.AddSingleton<UsersTableRepository>();
  }

A simple "dummy" controller with two filters defined on it. You can notice that I already done DI inside this controller by decorating the property with [FromServices] and it works.

[Route("[controller]")]
[BasicAuthenticationFilter(Order = 0)]
[BasicAuthorizationFilter("Admin", Order = 1)]
public class DummyController : Controller
{

    [FromServices]
    public UsersTableRepository UsersRepository { get; set; }

    // GET: /<controller>/
    [Route("[action]")]
    public IActionResult Index()
    {
        return View();
    }
}

Doing the same DI within BasicAuthenticationFilter does not work and at runtime UserRepository property is a null reference.

public class BasicAuthenticationFilterAttribute : AuthorizationFilterAttribute
{
    [FromServices]
    public UsersTableRepository UsersRepository { get; set; }

    public override void OnAuthorization(AuthorizationContext filterContext)

    {
        if (!Authenticate(filterContext.HttpContext))
        {
            // 401 Response
            var result = new HttpUnauthorizedResult();
            // Add the header for Basic authentication require
            filterContext.HttpContext.Response.Headers.Append("WWW-Authenticate", "Basic");
            filterContext.Result = result;

            //if (!HasAllowAnonymous(context))
            //{
            //    base.Fail(context);
            //}
        }
    }
    // ...
}

Any idea about how solve this?

Refrain from injecting dependencies into your attributes as explained here . Make your attributes passive , or make your attribute a humble object as described here .

    var dependencyScope = context.HttpContext.RequestServices;
    var usersRepository = dependencyScope.GetService(typeof(UsersTableRepository)) as UsersTableRepository;
    // usersRepository is now ready to be used

So your BasicAuthenticationFilter will look like this:

public class BasicAuthenticationFilterAttribute : AuthorizationFilterAttribute
{
    public UsersTableRepository UsersRepository { get; set; }

    public override void OnAuthorization(AuthorizationContext filterContext)

    {
        var dependencyScope = context.HttpContext.RequestServices;
        UsersRepository = dependencyScope.GetService(typeof(UsersTableRepository)) as UsersTableRepository;
        
        if (!Authenticate(filterContext.HttpContext))
        {
            // 401 Response
            var result = new HttpUnauthorizedResult();
            // Add the header for Basic authentication require
            filterContext.HttpContext.Response.Headers.Append("WWW-Authenticate", "Basic");
            filterContext.Result = result;

            //if (!HasAllowAnonymous(context))
            //{
            //    base.Fail(context);
            //}
        }
    }
    // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM