Register Iauthenticationmanager with Simple Injector

Register IAuthenticationManager with Simple Injector

What you are doing with IAuthenticationManager registration worked for me with no issues. At some point I was getting the same exception as you were getting, but that was caused by line with

container.Verify();

just after the container configuration. It was trying to create all instances of registered objects, but there was no HttpContext.Current present, hence the exception.

Are you not getting any instances out of container before any HTTP request is available? If you really need them, then the only way to work around this is use Factory, as suggested by NightOwl888. If you don't need container before the HTTP request, then refactor, so it is not use outwith HTTP request.

Setup Simple Injector with ASP.NET Identity 2.2.1

So between the help Ric .Net (which I've posted above as part of the question) and Lucas Teles answer in another question I've finally got my answer. Lucas suggested adding these lines to my Simple Injector setup:

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

So now my container building method looks like this:

public static Container GetInitializeContainer(IAppBuilder app)
{
var container = new Container();

// IoC for ASP.NET Identity
container.RegisterSingleton<IAppBuilder>(app);
container.Register<ApplicationUserManager>(Lifestyle.Scoped);
container.Register<ApplicationDbContext>(
() => new ApplicationDbContext("Your constring goes here"),
Lifestyle.Scoped);
container.Register<IUserStore<ApplicationUser>>(
() => new UserStore<ApplicationUser>(
container.GetInstance<ApplicationDbContext>()),
Lifestyle.Scoped);
container.RegisterInitializer<ApplicationUserManager>(
manager => InitializeUserManager(manager, app));
// Setup for ISecureDataFormat
container.Register<ISecureDataFormat<AuthenticationTicket>,
SecureDataFormat<AuthenticationTicket>>(Lifestyle.Scoped);
container.Register<ITextEncoder, Base64UrlTextEncoder>(Lifestyle.Scoped);
container.Register<IDataSerializer<AuthenticationTicket>,
TicketSerializer>(Lifestyle.Scoped);
container.Register<IDataProtector>(
() => new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider()
.Create("ASP.NET Identity"),
Lifestyle.Scoped);

// Register all controllers
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());

return container;
}

Register single class with Simple Injector

Simpleinjector doesn't like classes or services having multiple constructors. It considers them a code smell IIRC.

You could do something like:

container.Register(() => new LawyersDb(container.GetInstance(typeof(SQLDatabase)), Lifestyle.Scoped);

You'd need to set your scoping and get the instance of the SQLDatabase that you want to use in the class.

Simple Injector Identity UserManagerAppUser, Int32 Registration Error

The exception message says:

The constructor of type UserManager<AppUser, int> contains the parameter of type
IUserStore with name 'store' that is not registered. Please ensure
IUserStore<AppUser, int> is registered, or change the constructor of UserManager.

The exception suggests that you should make a registration for IUserStore<AppUser, int>, because the UserManager<AppUser, int> depends on this. So you could for instance make the following registration:

// UserStore<TUser> is defined in Microsoft.AspNet.Identity.EntityFramework.
// Do note that UserStore<TUser> implements IUserStore<TUser, string>, so
// this Entity Framework provider requires a string. If you need int, you
// might have your own store and need to build your own IUserStore implemenation.
container.Register<IUserStore<AppUser, string>>(
() => new UserStore<AppUser>>(),
Lifestyle.Scoped);

However, according to this article, you should not auto-wire framework types such as UserManager<TUser, TKey>, but use manual registration instead by creating such type yourself. For instance:

container.Register<UserManager<AppUser, string>>(
() => new UserManager<AppUser, string>(new UserStore<AppUser>()),
Lifestyle.Scoped);

It would be even better to refrain from using types from external libraries (such as the UserManager<TUser, TKey>) directly in your core application. Especially since you are practicing the Onion architecture. This architecture promotes SOLID principles and describes the concept of ports and adapters. A port is an abstraction defined by your application that allows a gateway into some external domain or library. An adapter is an implementation of such abstraction that actually connects to this external domain or library. This is exactly what the Dependency Inversion Principle (one of the five SOLID principles) describes.

So instead of letting your UserRepository depend on a framework type such as UserManager<TUser, TKey>, let it depend on a customly defined abstraction, with a very narrowly defined and single responsibility. The adapter for this abstraction can on its turn use UserManager<TUser, TKey>.

Depending on what UserRepository does, you might even consider this UserRepository itself an adapter. In this case, letting UserRepository depend directly on UserManager<TUser, TKey> is fine. In that case, hiding the UserManager<TUser, TKey> behind an extra abstraction just causes an extra/needless layer of abstraction.

But nonetheless, the adapter can not only directly depend on UserManager<TUser, TKey>, but it can simply control the creation and destruction of UserManager<TUser, TKey> itself. In other words, your UserRepository can look as follows:

// NOTE: Do not let IUserRepository implement IDisposable. This violates
// the Dependency Inversion Principle.
// NOTE2: It's very unlikely that UserRepository itself needs any disposal.
public class UserRepository : IUserRepository
{
// This is Identity UserManager
private readonly IAuthenticationManager _authenticationManager;

public UserRepository(IAuthenticationManager authenticationManager)
{
_authenticationManager = authenticationManager;
}

public void Delete(AppUser user) {
// Here we create and dispose the UserManager during the execution
// of this method.
using (manager = new UserManager<AppUser, string>(
new UserStore<AppUser>())) {
manager.DeleteAsync(user).Result;
}
}
}

In the Simple Injector discussions there is an interesting description about how to work with Identity and Visual Studio's default template. And here is a Stackoverflow q/a about Identity that you might find interesting as well.

How to register collection of instances in Simple injector

You only have one type (DbContextProvider) that is responsible for constructing both AccountingContext and ActiveDirectryContext. From that perspective, it is really strange to create two DbContextProvider instances that are each partly initialized. A consumer would not expect GetAccountingDbContext() to return null or throw a NullReferenceException. So instead, you should create one single instance that can be used for both cases:

container.Register<ActiveDirectryContext>(Lifestyle.Scoped);
container.Register<AccountingContext>(Lifestyle.Scoped);

container.RegisterInstance<DbContextProvider>(new DbContextProvider
{
ActiveDirectryDbContextResolver = () => container.GetInstance<ActiveDirectryContext>(),
AccountingDbContextResolver = () => container.GetInstance<AccountingContext>()
});

Or better, make DbContextProvider immutable:

container.RegisterInstance<DbContextProvider>(new DbContextProvider(
activeDirectryDbContextResolver: () => container.GetInstance<ActiveDirectryContext>(),
accountingDbContextResolver: () => container.GetInstance<AccountingContext>()));

This fixes the problem, because there is no only one registration for DbContextProvider. This removes the ambiguity, prevents possible bugs, and is a simpler solution.

But while this would work, I would like to suggest a few changes to your design.

Composition over Inheritance

First of all, you should get rid of the ServiceBase base class. Although base classes are not bad per see, when they start to get dependencies of their own, they likely start to violate the Single Responsibility Principle, and their derivatives the Dependency Inversion Principle and the Open/Closed Principle:

  • Base classes with dependencies often become a hodgepodge of functionality—often cross-cutting concerns. The base class becomes an ever-growing class. Ever-growing classes are an indication of a Single Responsibility Principle violation.
  • When the base class starts to contain logic, the derivatives automatically depend on that behavior—A derivative is always strongly coupled to its base class. This makes it hard to test the derivative in isolation. In case you ever want to replace or mock the behavior of the base class, it means that its behavior is Volatile. When a class is tightly coupled with a Volatile Dependency, it means you are violating the Dependency Inversion Principle.
  • The base class's constructor dependencies need to be supplied by the derived class's constructor. This will cause sweeping changes when the base class requires a new dependency, because all derived constructors need to be updated as well.

Instead, of using base classes, do the following:

  • Instead of forwarding dependencies from the derived class to the base class constructor, the derived class should store the dependency itself in a private field. It can use that dependency directly.
  • In case the base class contains behavior besides code:
    • In case that behavior is Volatile, wrap the logic in a class, hide that class behind an abstraction and inject the class (through its abstraction) into the constructor of the derived class. When doing this, it becomes very easy to see what dependencies the derived class has.
    • In case the behavior is Stable, you can use static helper classes or extension methods to make the base class's behavior reusable.
    • In case the behavior concerns a cross-cutting concern, consider the use of Decorators or Dynamic Interception as an alternative to base classes.

When you follow this advice, what you end up with is a set of (derived) service classes that depend on a base class that is nothing more than an empty shell. This is when you can remove the base class altogether. What you now achieved is Composition over Inheritance. Composition typically leads to more maintainable systems than inheritance does.

Closure Composition Model

As JoostK mentioned, you can also inject the DbContext types directly into consumers. Whether or not you want to do this, however, depends on the type of composition model you decided to use. What this means is that, when you choose to apply the Closure Composition Model, you should typically inject the DbContext implementations directly into your consumers.

public class ProduceIncomeTaxService : IHandler<ProduceIncomeTax>
{
private readonly AccountingContext context;

// Inject stateful AccountingContext directly into constructor
public ProduceIncomeTaxService(AccountingContext context) => this.context = context;

public void Handle(ProduceIncomeTax command)
{
var record = this.context.AccountingRecords
.Single(r => r.Id == command.Id);

var tax = CalculateIncomeTax(record);

FaxIncomeTax(tax);

this.context.SaveChanges();
}

...
}

This simplifies the registrations of your system, because now you just register the DbContext implementaions and you're done:

container.Register<ActiveDirectryContext>(Lifestyle.Scoped);
container.Register<AccountingContext>(Lifestyle.Scoped);

// Of course don't forget to register your service classes.

Interface Segregation Principle

Your current DbContextProvider seems to designed around the Ambient Composition Model. There are advantages of both composition models, and you might have chosen deliberately for the Ambient Composition Model.

Still, however, the DbContextProvider exposes many (10) properties—one for each DbContext. Classes and abstractions with many methods can cause a number of problems concerning maintainability. This stems from the Interface Segregation Principle that prescribes narrow abstractions. So instead of injecting one wide provider implementation that gives access to a single DbContext type. Implementations would typically only require access to a single DbContext type. If they require multiple, the class should almost certainly be split up into smaller, more-focused classes.

So what you can do instead is create a generic abstraction that allows access to a single DbContext type:

public interface IDbContextProvider<T> where T : DbContext
{
T Context { get; }
}

When used in a consumer, this would look as follows:

public class ProduceIncomeTaxService : IHandler<ProduceIncomeTax>
{
private readonly IDbContextProvider<AccountingContext> provider;

// Inject an ambient context provider into the constructor
public ProduceIncomeTaxService(IDbContextProvider<AccountingContext> provider)
=> this.provider = provider;

public void Handle(ProduceIncomeTax command)
{
var record = this.provider.Context.AccountingRecords
.Single(r => r.Id == command.Id);

var tax = CalculateIncomeTax(record);

FaxIncomeTax(tax);

this.provider.Context.SaveChanges();
}

...
}

There are multiple ways to implement IDbContextProvider<T>, but you can, for instance, create an implementation that directly depends on Simple Injector:

public sealed class SimpleInjectorDbContextProvider<T> : IDbContextProvider<T>
where T : DbContext
{
private readonly InstanceProducer producer;

public SimpleInjectorDbContextProvider(Container container)
{
this.producer = container.GetCurrentRegistrations()
.FirstOrDefault(r => r.ServiceType == typeof(T))
?? throw new InvalidOperationException(
$"You forgot to register {typeof(T).Name}. Please call: " +
$"container.Register<{typeof(T).Name}>(Lifestyle.Scope);");
}

public T Context => (T)this.producer.GetInstance();
}

This class uses the injected Container to pull the right InstanceProducer registration for the given DbContext type. If this is not registered, it throws an exception. The InstanceProducer is then used to get the DbContext when Context is called.

Since this class depends on Simple Injector, it should be part of your Composition Root.

You can register it as follows:

container.Register<ActiveDirectryContext>(Lifestyle.Scoped);
container.Register<AccountingContext>(Lifestyle.Scoped);

container.Register(
typeof(IDbContextProvider<>),
typeof(SimpleInjectorDbContextProvider<>),
Lifestyle.Singleton);

using simple injector in mvc6 with cookie auth

The CrossWire extension method in the integration package makes a delegate registration in Simple Injector that allows Simple Injector to 'know' about the service, while the ASP.NET 5 configuration system is still in control of building that service. You can do the same yourself as follows:

container.Register(() => app.ApplicationServices.GetRequiredService<ISomeService>());

The CrossWire extension method seems rather useless, since it seems a one-liner to do it yourself, but CrossWire does one extra thing, which is suppressing the diagnostic warning that is thrown when a transient component implements IDisposable. This works around design flaws in ASP.NET 5, because there are abstractions in ASP.NET 5 that implement IDisposable, while abstractions should never implement IDisposable (abstractions that do, violate the Dependency Inversion Principle).

But this brings me to the next point, CrossWire always makes the registration in Simple Injector as transient, even though in ASP.NET the registration might be scoped or singleton. Which lifestyle a component has in ASP.NET is often an implementation detail, and might change from time to time. Or at least, the lifestyle is unknown to both the user and Simple Injector. That's why it is safest to give all cross-wired registrations the transient lifestyle by default. This does mean however that all dependent application components should be transient as well to prevent Captive Dependencies (a.k.a. Lifestyle Mismatches). I would say this is typically not a problem, because application components that depend ASP.NET services are very ASP.NET related. It's unlikely that you have core application components depend on ASP.NET stuff, because that would violate the Dependency Inversion Principle and might lead to hard to maintain code.

In your case you can do a few things. Simplest thing to do is to make SignInManager transient as well. It seems unlikely that it has any state that it should maintain over a single request, and when it does, that state should probably not belong there anyway (Single Responsibility Violation).

Another option is to cross wire the IHttpContextAccessor as singleton in Simple Injector. This is valid, because this service is registered as singleton in ASP.NET as well. This won't cause any hidden Captive Dependencies (unless Microsoft changes the lifetime in the future; in that case we're all screwed). You can do it like this:

container.RegisterSingleton(app.ApplicationServices.GetRequiredService<IHttpContextAccessor>());

Your third option is to prevent registration of this IHttpContextAccessor completely. It is by itself already a Dependency Inversion Principle violation for your application code. It's a DIP violation, because IHttpContextAccessor is not defined by your application but by the framework. It will therefore never be defined in a way that exactly suits your application needs. Your application code will hardly ever need to get a HttpContext object. Rather it is interested in some particular value such as a UserId, TenantId, or other contextual value. So instead, your application is much better of when it depends on an IUserContext, ITenantContext or other specific abstraction. Whether or not the value is extracted from the HttpContext is an implementation detail.

Such implementation (adapter) can resolve the IHttpContextAccessor at runtime and get the HttpContext from it. The implementation of such adapter would most of the time be really simple of course, but this is fine; our goal is simply to shield the application from this knowledge. Since the adapter has knowledge about the ASP.NET abstraction, it is fine for it to resolve services from it configuration. The adapter is merely an anti-corruption layer.

These are basically your options.

ASP.NET MVC 5 + Owin + SimpleInjector

I think the exception is thrown when you call Verify(). Probably at that line, but only when the delegate is called.

Simple Injector allows making registrations in any order and will therefore not verify the existence and correctness of a registration’s dependencies. This verification is done the very first time an instance is requested, or can be triggered by calling .Verify() at the end of the registration process.

I suspect you're registrering the OwinContext only because you need it for getting the IAuthenticationManager.

The problem you face is that the OwinContext is only available when there is a HttpContext. This context is not available at the time the application is build in the composition root. What you need is a delegate which checks the stage of the application and returns a component that matches this stage. You could that by registering the IAuthenticationManager as:

container.RegisterPerWebRequest<IAuthenticationManager>(() => 
AdvancedExtensions.IsVerifying(container)
? new OwinContext(new Dictionary<string, object>()).Authentication
: HttpContext.Current.GetOwinContext().Authentication);

The delegate will return the Owin controlled IAuthenticationManager when the code runs at 'normal runtime stage' and there is a HttpContext.

But when making an explicit call the Verify() (which is highly advisable to do!) at the end of registration process there is no HttpContext. Therefore we will create a new OwinContext during verifying the container and return the Authentication component from this newly created OwinContext. But only if the container is indeed verifying!

A full and detailed description can be read here as already mentioned in the comments.



Related Topics



Leave a reply



Submit