Simple Injector and default AccountContoller depen

2019-05-04 12:26发布

问题:

I have problem with Simple Injector in my Web Api project. I user default AccountController generated by VS.

public AccountController(ApplicationUserManager userManager,
    ISecureDataFormat<AuthenticationTicket> accessTokenFormat)

In my configuration file I register:

var container = new Container();

// This is an extension method from the integration package.
container.RegisterWebApiFilterProvider(config);
container.RegisterWebApiControllers(config);

container.Register<IInitializeService, InitializeService>();
container.Register<IFolderRepository, FolderRepository>();
container.Register<IUserRepository, UserRepository>();
container.Register<ILogger, Logger>();

//Authentication Wrap
container.Register<IUserStore<User, Guid>, ApplicationUserStore>();
container.Register<IDataSerializer<AuthenticationTicket>, TicketSerializer>();
container.Register<ISecureDataFormat<AuthenticationTicket>,
    SecureDataFormat<AuthenticationTicket>>();
container.Register<IDataProtector>(
    () => new DpapiDataProtectionProvider().Create("ASP.NET Identity"));

container.Verify();

// 4. Register the container as MVC3 IDependencyResolver.
DependencyResolver.SetResolver(new SimpleInjectorWebApiDependencyResolver(container));
config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);

I though that Simple Injector will be smart enough to handle all build in dependences responsible for default identity and i wont need to register them manually, but I'm getting exceptions if I wont register them.

Still getting an exception:

The constructor of type SecureDataFormat contains the parameter of type ITextEncoder with name 'encoder' that is not registered. Please ensure ITextEncoder is registered in the container, or change the constructor of SecureDataFormat.

Is there any way to handle that automatically?

回答1:

I implemented a Web Api and I wrote this code. This works for me

container.RegisterWebApiRequest<ISecureDataFormat<AuthenticationTicket>, SecureDataFormat<AuthenticationTicket>>();
container.RegisterWebApiRequest<ITextEncoder, Base64UrlTextEncoder>();
container.RegisterWebApiRequest<IDataSerializer<AuthenticationTicket>, TicketSerializer>();
container.RegisterWebApiRequest<IDataProtector>(() => new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider().Create("ASP.NET Identity"));


回答2:

How is the container supposed to know which implementation of ITextEncoder you want to use in the constructor of SecureDataFormat?

You have to tell it which one to use. I think the rules basically go something like this:

if an interface is required (by a constructor) then it needs to know which implementation to use. If a concrete class is required it will automatically build an instance of that class (assuming it can resolve all the types that class needs).

As your SecureDataForms needs an interface you have to register one, otherwise its only option would be to 'guess' at which implementation you want and this could then go wrong silently if more than one implementation existed.



回答3:

I just came up against this issue. I'm using ninject but you'll get the idea. Here is my binding:

kernel.Bind<ITextEncoder>().To<Base64UrlTextEncoder>();

According to the source, the only thing I ever see being used to new up an instance of SecureDataFormat is Base64UrlTextEncoder. So it seemed like a safe bet to use, but it's certainly not clear to me at first glance how to appropriately use this constructor overload.