1

Trying to inject property to my custom AuthorizeAttribute but this attribute always comes null. Is this registration wrong?

public class AuthenticateAttribute : AuthorizeAttribute
{
    public IAuthenticationService authenticationService { get; set; }
    public UserTypes UserType;
    public AuthenticateAttribute()
    {

    }
}

Calling From Global Asax

public static void InitializeDependencies()
    {
        var builder = new ContainerBuilder();
        var config = GlobalConfiguration.Configuration;
        builder.RegisterAssemblyTypes(Assembly.Load("BusinessServices"))
                 .Where(t => t.Name.EndsWith("Service"))
                 .AsImplementedInterfaces()
                 .InstancePerLifetimeScope();
        builder.RegisterAssemblyTypes(Assembly.Load("BusinessEntities"))
                 .Where(t => t.Name.EndsWith("Helper"))
                 .AsImplementedInterfaces()
                 .InstancePerLifetimeScope();
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
        builder.RegisterWebApiFilterProvider(config);
        builder.Register(x => new ApiExceptionHandler(x.Resolve<ILogService>())).AsWebApiExceptionFilterFor<ApiController>().InstancePerLifetimeScope();
        builder.RegisterType<AuthenticateAttribute>().PropertiesAutowired().InstancePerLifetimeScope();
        var container = builder.Build();
        config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
    }

Authentication Service

public class AuthenticationService : IAuthenticationService
{
    private readonly IUnitOfWork unitOfWork;
    private readonly IAutoMapperHelper mapper;
    public AuthenticationService(IUnitOfWork _unitOfWork, IAutoMapperHelper _mapper)
    {
        unitOfWork = _unitOfWork;
        mapper = _mapper;
    }
}

I can't use authenticate attribute as constructor injected because i can't use it on methods.

    [Authenticate] //How can i pass authenticationService parameter to it, if i use constructor injection?
    [HttpPost]
    public async Task<ConnectSocialPlatformsResponseModel> ConnectSocialPlatforms(ConnectSocialPlatformsRequestModel model)
    {
        if (ModelState.IsValid)
            return await authenticationService.ConnectSocialPlatforms(model);
        else
            return validationHelper.CreateResponse<ConnectSocialPlatformsResponseModel>(ModelState);
    }
Tugrul Emre Atalay
  • 918
  • 1
  • 9
  • 28
  • 4
    You could use [constructor injection with AuthorizeAttribute](http://stackoverflow.com/a/32254851/181087), which is a better idea. Property injection into attributes requires hacks to get to work, but WebApi can be extended to inject filters with constructor-injected dependencies. See [passive attributes](http://blog.ploeh.dk/2014/06/13/passive-attributes/) for the details. – NightOwl888 Jan 25 '17 at 07:58
  • @NightOwl888 thank you for answer but there are some reasons to use attribute. – Tugrul Emre Atalay Jan 25 '17 at 14:04
  • Can you manually resolve an `IAuthenticationService`? Also, I'm sure you [read the docs](http://autofac.readthedocs.io/en/latest/integration/webapi.html) and recognized that standard Web API filters are *singletons* so the `InstancePerLifetimeScope` there isn't going to work the way you think it will? – Travis Illig Jan 25 '17 at 16:28
  • 2
    Also, can you be specific about which thing is coming out null? The question says "the attribute comes out null" but I'm guessing you're talking about the `IAuthenticationService`. Are you also including the `UserType` field? (Fields aren't injectable...) – Travis Illig Jan 25 '17 at 17:18
  • @TuğrulEmreAtalay - If you have "reasons to use an attribute", you can still use an attribute in addition to a global filter - there is nothing stopping you. But to get it working, you have to recognize that *filters* are what do the heavy lifting in WebApi. Attributes are simply meta-data. If you separate your concerns this way, there is no reason to inject services into an attribute because attributes have no behavior anyway. – NightOwl888 Jan 25 '17 at 21:17
  • @TravisIllig - Filters are only singletons if you register them statically with the framework. If you instead use an [IFilterProvider](https://msdn.microsoft.com/en-us/library/system.web.http.filters.ifilterprovider(v=vs.118).aspx) injected with the container in your composition root, you can inject dependencies with lifetimes shorter than singleton. – NightOwl888 Jan 25 '17 at 21:21
  • @TuğrulEmreAtalay - BTW - AuthorizeAttribute *is* a filter (and for that matter, so are Controllers). The framework uses Reflection to scan for attributes that are also filters and register them as a filter with WebApi. All I am proposing is you bypass the automagic step that uses Reflection to instantiate your filter so you can use the constructor. [Here is another example](http://stackoverflow.com/a/28365933/181087) that might make this more clear. – NightOwl888 Jan 25 '17 at 21:30
  • @NightOwl888 I'm aware. I'm one of the Autofac project owners. I wrote the docs. – Travis Illig Jan 25 '17 at 22:04
  • @NightOwl888 AuthenticaionService is constructor injected. So i can't create object from attribute. If i use constructor injection, i can't use it at controllers, it gives wrong type parameter. – Tugrul Emre Atalay Jan 26 '17 at 12:15
  • @TravisIllig i am talking about authenticationService. I resolved manually too, but it didnt worked too. – Tugrul Emre Atalay Jan 26 '17 at 12:17
  • What do you mean you tried to resolve it manually but it didn't work? Exception? Please update the body of the question with that info. Include the code you used when trying to resolve manually and exactly what happened when you tried. – Travis Illig Jan 26 '17 at 13:12
  • @TravisIllig what do you mean resolving manually? I'll update question when i reach my pc. – Tugrul Emre Atalay Jan 26 '17 at 16:08
  • I've edited code @TravisIllig – Tugrul Emre Atalay Jan 26 '17 at 17:00
  • Where is `IUnitOfWork` registered? If you try to resolve `IAuthenticationService` manually does it resolve or do you get an exception? – Travis Illig Jan 26 '17 at 18:07
  • I've cuted code, its already registered at bootstrapper. builder.RegisterType(typeof(UnitOfWork)).As(typeof(IUnitOfWork)).InstancePerLifetimeScope(); Could you give me manullay resolve code that you are talking about? @TravisIllig – Tugrul Emre Atalay Jan 26 '17 at 19:25
  • `container.Resolve();` – Travis Illig Jan 26 '17 at 19:29
  • @TravisIllig where will i get container in attribute? – Tugrul Emre Atalay Jan 26 '17 at 19:49
  • Just try resolving it from _somewhere_ - inside a controller, inside some other service. The point is to determine if there is a problem or missing dependency with `IAuthenticationService`. We're trying to walk through it step by step to make sure pieces are in place. – Travis Illig Jan 26 '17 at 19:51
  • It's working at my controller :( – Tugrul Emre Atalay Jan 26 '17 at 20:03
  • 1
    One way can be, do not pass dependency into constructor and set then using this: `IUnitOfWork unitofWork = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IUnitOfWork)) as IUnitOfWork;` into constructor; – Manprit Singh Sahota Jan 27 '17 at 10:15
  • @ManpritSinghSahota it worked! Thanks. – Tugrul Emre Atalay Jan 27 '17 at 15:12

0 Answers0