0

I am trying to find out how I can pass the StructrueMap container to a class that I wrote that inherits from another (MS-Class).

namespace TheNamespace
{
  public class DatabaseIssuerNameRegistry : ValidatingIssuerNameRegistry
  {
    /* **This can't be done**
    public DatabaseIssuerNameRegistry(IPortalTenantManager portalTenantManager)
    {
        _someField= portalTenantManager;
    }*/


    protected override bool IsThumbprintValid(string thumbprint, string issuer)
    {
       //How does it work ???????????

       var portalTenantManager = container.GetInstance<IPortalTenantManager>();
      //Do something with the portalTenantManager
    }
}

I need portalTenantManager to be the Instance that I have defined in my container in the Global.asax.

My Global Assax has these things setup:

protected void Application_Start()
{
 var container = new Container();
 container.Configure(x =>
            { ....
              ....
             x.For<IPortalTenantManager>().Use<PortalTenantManager>();
             });

...

...
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory(container));
...
GlobalConfiguration.Configuration.DependencyResolver = new StructureMapApiControllerFactory(container);
...
    }

Edit: Because of the comments of @NightOwl888 I'll explain a bit further what this class does. (Hopefully explaining so why my hands are tied)

My application is able to authenticate a user with Azure Active Directory and is Multi-tenant capable. In the authentication pipeline I have the possibility to store the validation endpoints in my database instead of the default way on the web.config file. See MSDN and this, which actually is explaining exactly what I'm doing.

So I registered my class in the web.config under the Tag issuerNameRegistry. At some point of the validation pipeline my class is instantiated and the overriden method IsThumbprintValid is beeing called. The problem is that the class registered in issuerNameRegistry expects a parameterless constructor (there it is! the constrained construction!), therefore I cannot create a constructor that would solve my problem.

Thanks for your help

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
CodeHacker
  • 2,127
  • 1
  • 22
  • 35
  • It would be helpful if you explain why adding the constructor can't be done, as it would seem to be the most obvious solution to the problem. – NightOwl888 Dec 30 '15 at 15:56
  • I don't now, it just wont let me do it. This class is called somewhere in the pipeline of IIS during authentication whit Azure-AD. If I create the constructor public DatabaseIssuerNameRegistry(IPortalTenantManager portalTenantManager).. It fails – CodeHacker Dec 30 '15 at 16:25
  • How is it that you expect that your new class will be used by the framework? Why haven't you posted a link to the documentation of the framework? You need to make it clear how your class is instantiated, and that it is not done using [constrained construction](http://blog.ploeh.dk/2011/04/27/Providerisnotapattern/). – NightOwl888 Dec 30 '15 at 17:54
  • Thanks @NightOwl88 for your comment. I've edited the question a bit, including some links , as you suggested, and read your link about the constrained construction,but that's the way it is! – CodeHacker Dec 31 '15 at 07:21

1 Answers1

1

It turns out that this question has been asked before on MSDN, the answer of which was provided by Travis Spencer in 2 different posts.

it is typical in my experience to have a single container and use that service- or Web-side-wide. In the startup of the service or Web app, you can create the container, register the dependencies, new up an instance of your SecurityTokenServiceConfiguration class, resolve your dependencies, use it to punch out a SecurityTokenService object, and host it.

After the first beta, we really pushed for DI support. We got a little hook in beta 2. You can now create a custom SecurityTokenServiceConfiguration class that overrides the virtual CreateSecurityTokenService method. The implementation in Microsoft's SecurityTokenServiceConfiguration does Activator.CreateInstance; yours can do IoC. This can include the resolution of an IssuerNameRegistiry. Something like this perhaps:

RequestSecurityTokenResponse Issue(IClaimsPrincipal principal, RequestSecurityToken request)
{
    SecurityTokenServiceConfiguration config = new MyGoodSecurityTokenServiceConfiguration();
    SecurityTokenService sts = config.CreateSecurityTokenService();
    RequestSecurityTokenResponse rstr = sts.Issue(principal, request);

    return rstr;
}

public class MyGoodSecurityTokenServiceConfiguration : SecurityTokenServiceConfiguration
{
    public override SecurityTokenService CreateSecurityTokenService()
    {
        IssuerNameRegistry = IoC.Resolve<IssuerNameRegistry>();
    
        var sts = IoC.Reslove<SecurityTokenService>();

        return sts;
    }
}

Of course, this means that you need to create a static instance of your DI container so it is accessible to your SecurityTokenServiceConfiguration class. Personally, I don't like that idea because it makes your DI container accessible throughout the application, which can lead to abuse of the DI container as a service locator.

Ideally, there would be a way in any DI friendly framework to pass the container into an abstract factory in order to resolve service dependencies. However, since I am not familiar with WIF it is unclear whether that can be done - perhaps the class where the Issue method exists could have a constructor added? The trick is to keep walking up the chain until you find the first place in the framework where you can intervene and do all of your DI configuration there.

Community
  • 1
  • 1
NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • Thanks for the reply, the "problem" I have, I'm trying to get rid of my static instance of the DI container...so well,having no way to add a constructor, I had to create a new instance of my container.Code smells.. but I'll leave it for now. – CodeHacker Jan 04 '16 at 08:06
  • I suppose a possible alternative solution would be to make an abstract factory that is set in a static method that your WIF classes can access to resolve `IssuerNameRegistry` and `SecurityTokenService`. Then inject your container into the implementation of the factory. At least then you wouldn't be exposing the container to the rest of the application for abuse as a service locator. – NightOwl888 Jan 04 '16 at 13:56