I'm using Unity for Dependencies Injection and using Identiy Provider to manage the user login, register, email confirmation, etc.
When I try to register a user, I have this problem:
The current type, Microsoft.Owin.Security.IAuthenticationManager, is an interface and cannot be constructed. Are you missing a type mapping?
I have no idea how to register this Interface (IAuthenticationManager) in my Unity container.
I tried registering the interface with this code, but if I put it, I have other problem:
No IUserTokenProvider is registered.
container.RegisterType<HttpContextBase>(
new InjectionFactory(_ => new HttpContextWrapper(HttpContext.Current)));
container.RegisterType<IOwinContext>(new InjectionFactory(c => c.Resolve<HttpContextBase>().GetOwinContext()));
container.RegisterType<IAuthenticationManager>(
new InjectionFactory(c => c.Resolve<IOwinContext>().Authentication));
I put some code of the app (If I don't use Unity, all work fine):
AccountController
private IAuthenticationManager AuthenticationManager
{
get
{
return HttpContext.GetOwinContext().Authentication;
}
}
IdentityConfig.cs
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options,
IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug in here.
manager.RegisterTwoFactorProvider("PhoneCode", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is: {0}"
});
manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<ApplicationUser>
{
Subject = "SecurityCode",
BodyFormat = "Your security code is {0}"
});
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
}
// Configure the RoleManager used in the application. RoleManager is defined in the ASP.NET Identity core assembly
public class ApplicationRoleManager : RoleManager<IdentityRole>
{
public ApplicationRoleManager(IRoleStore<IdentityRole, string> roleStore)
: base(roleStore)
{
}
public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
{
return new ApplicationRoleManager(new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>()));
}
}
public class EmailService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
// Plug in your email service here to send an email.
return Task.FromResult(0);
}
}
public class SmsService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
// Plug in your sms service here to send a text message.
return Task.FromResult(0);
}
}
// This is useful if you do not want to tear down the database each time you run the application.
// public class ApplicationDbInitializer : DropCreateDatabaseAlways<ApplicationDbContext>
// This example shows you how to create a new database if the Model changes
public class ApplicationDbInitializer : DropCreateDatabaseIfModelChanges<ApplicationDbContext>
{
protected override void Seed(ApplicationDbContext context)
{
InitializeIdentityForEF(context);
base.Seed(context);
}
//Create [email protected] with password=Admin@123456 in the Admin role
public static void InitializeIdentityForEF(ApplicationDbContext db)
{
var userManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
var roleManager = HttpContext.Current.GetOwinContext().Get<ApplicationRoleManager>();
const string name = "[email protected]";
const string password = "Admin@123456";
const string roleName = "Admin";
//Create Role Admin if it does not exist
var role = roleManager.FindByName(roleName);
if (role == null)
{
role = new IdentityRole(roleName);
var roleresult = roleManager.Create(role);
}
var user = userManager.FindByName(name);
if (user == null)
{
user = new ApplicationUser { UserName = name, Email = name };
var result = userManager.Create(user, password);
result = userManager.SetLockoutEnabled(user.Id, false);
}
// Add user admin to Role Admin if not already added
var rolesForUser = userManager.GetRoles(user.Id);
if (!rolesForUser.Contains(role.Name))
{
var result = userManager.AddToRole(user.Id, role.Name);
}
}
}
public class ApplicationSignInManager : SignInManager<ApplicationUser, string>
{
public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager)
:
base(userManager, authenticationManager)
{
}
public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
{
return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
}
public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context)
{
return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication);
}
}
Thanks!!
Here is what I did to make Unity play nice with ASP.NET Identity 2.0:
I added the following to the RegisterTypes
method in the UnityConfig
class:
container.RegisterType<DbContext, ApplicationDbContext>(
new HierarchicalLifetimeManager());
container.RegisterType<UserManager<ApplicationUser>>(
new HierarchicalLifetimeManager());
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(
new HierarchicalLifetimeManager());
container.RegisterType<AccountController>(
new InjectionConstructor());