Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency Injection in WCF ClaimsAuthenticationManager

I have successfully configured DI for my WCF services using Ninject. Each service class has a constructor into which Ninject injects instances at runtime.

public class MessageService : ServiceBase,IMessageService
    {           
        private readonly IMessageRepository _messageRepository;
        private readonly IMappingEngine _mapper;  // AutoMapper mapping engine

        // Instances injected in constructor by Ninject
        public MessageService(IMessageRepository messageRepository, IMappingEngine mapper)
        {
            _messageRepository = messageRepository;
            _mapper = mapper;
        }     
    ...
}

My understanding is that this is achieved by telling Wcf to use the NinjectServiceHostFactory to activate services.

All well and good... it works a treat.

I have a number of class libraries which are referenced by the wcf service project. One of these libraries has class which derives from ClaimsAuthenticationManager. It is designed to transform incoming claims to those which are domain specific. The WCF scaffolding instantiates this class at runtime as part of the identity pipeline. I would like have this class use a repository pattern to get the business roles of the identity from a database. It would then create a new ClaimsIdentity with domain specific claims. Now I could new up a repository instance, but i'd like Ninject to inject this at runtime. I created a constructor with an repository interface parameter in the utter naive hope that Ninject would just do it's stuff. WCF failed as it could not find a parameterless constructor.

How do I get Ninject to inject the instance when I essentially have no reference to the Ninject kernel within my class library?

My understanding is that the IoC container should be created at the composition root, which in my case is within the WCF service host. Since it is the Wcf pipeline which is instantiating my class I have no control over the process in order to wire up the dependency. Or do I?

like image 334
jcaddy Avatar asked Nov 03 '13 23:11

jcaddy


1 Answers

The only way to do it is to set System.IdentityModel.Services.FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthorizationManager programmatically in global.asax or wherever you want before WCF call.

protected void Application_Start()
{
    ...
    FederatedAuthentication.FederationConfigurationCreated += FederatedAuthentication_FederationConfigurationCreated;
    ...
}

void FederatedAuthentication_FederationConfigurationCreated(object sender, System.IdentityModel.Services.Configuration.FederationConfigurationCreatedEventArgs e)
{
    var cam = DependencyResolver.Current.GetService<ClaimsAuthenticationManager>();  // Instantiate your implementation here using any IoC you want.
    e.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager = cam;
}

If you will use global.asax, then don't forget to add to web.config:

<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
like image 76
Alexander Vasilyev Avatar answered Nov 14 '22 04:11

Alexander Vasilyev