Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Injecting dependencies into custom Web API action filter attribute with Autofac

I'm trying to resolve the dependencies of my custom AuthorizeAttribute which I use to decorate my API controllers in an MVC4 app. Problem is that I keep getting a NullReferenceException on the service dependency I use within my custom filter. Here is my Autofac configuration:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        var builder = new ContainerBuilder();
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
        builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerApiRequest();
        builder.RegisterType<DatabaseFactory>().As<IDatabaseFactory>().InstancePerApiRequest();
        builder.RegisterAssemblyTypes(typeof(UserProfileRepository).Assembly)
            .Where(t => t.Name.EndsWith("Repository"))
            .AsImplementedInterfaces().InstancePerApiRequest();

        builder.RegisterAssemblyTypes(typeof(IUserProfileMapper).Assembly)
            .Where(t => t.Name.EndsWith("Mapper"))
            .AsImplementedInterfaces().InstancePerApiRequest();

        builder.RegisterAssemblyTypes(typeof(UserProfileSvc).Assembly)
            .Where(t => t.Name.EndsWith("Svc"))
            .AsImplementedInterfaces().InstancePerApiRequest();

        builder.RegisterWebApiFilterProvider(config);
        var container = builder.Build();
        var resolver = new AutofacWebApiDependencyResolver(container);
        config.DependencyResolver = resolver;
    }
}

and my custom authorize filter:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    public IAuthenticationSvc _authenticationSvc;
    protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        if (!base.IsAuthorized(actionContext))
        {
            return false;
        }
        var trueUserId = WebSecurity.CurrentUserId;

        if (_authenticationSvc.GetUsersRoles(trueUserId).Any(x => x == "Admin")) return true;
        // NullReferenceException on _authenticationSvc
     }
}

According to the official docs all that is needed is:

var builder = new ContainerBuilder();
builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);

But that doesn't seem to do the trick either. Appreciate any help.

like image 461
Mohammad Sepahvand Avatar asked Apr 25 '14 19:04

Mohammad Sepahvand


3 Answers

I think Autofac's documentation offers much simpler solution for WebApi action filters.

public interface ServiceCallActionFilterAttribute : ActionFilterAttribute {   public override void OnActionExecuting(HttpActionContext actionContext)   {     // Get the request lifetime scope so you can resolve services.     var requestScope = actionContext.Request.GetDependencyScope();      // Resolve the service you want to use.     var service = requestScope.GetService(typeof(IMyService)) as IMyService;      // Do the rest of the work in the filter.     service.DoWork();   } } 

It is not "pure DI" as it is using service locator, but it is simple and works with the request scope. You don't need to worry about registering specific action filter for each WebApi controller.

Source: http://autofac.readthedocs.io/en/latest/integration/webapi.html#provide-filters-via-dependency-injection

like image 133
Martin Brabec Avatar answered Oct 11 '22 17:10

Martin Brabec


You should configure property injection for your attribute

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    public IAuthenticationSvc AuthenticationSvc { get; set; }
}

and the builder

builder.RegisterType<MyAuthorizeAttribute>().PropertiesAutowired();
like image 20
Toan Nguyen Avatar answered Oct 11 '22 16:10

Toan Nguyen


In addition to @Toan Nguyen's answer, if you have this...

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    public IAuthenticationSvc AuthenticationSvc { get; set; }
}

... it seems you also need (or may need) the first line below:

builder.RegisterFilterProvider();
builder.RegisterType<MyAuthorizeAttribute>().PropertiesAutowired();

Reference: http://itprojectpool.blogspot.com.au/2014/03/autofac-di-on-action-filters.html

like image 24
jwwishart Avatar answered Oct 11 '22 15:10

jwwishart