Unity for Dependencies Injectionを使用し、Identiy Providerを使用してユーザーログイン、登録、確認メールなどを管理しています。
ユーザーを登録しようとすると、この問題が発生します。
現在のタイプMicrosoft.Owin.Security.IAuthenticationManagerはインターフェースであり、構築できません。型マッピングがありませんか?
Unityコンテナにこのインターフェイス(IAuthenticationManager)を登録する方法がわかりません。
私はこのコードでインターフェイスを登録しようとしましたが、それを置くと、他の問題があります:
IUserTokenProviderは登録されていません。
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));
アプリのコードをいくつか追加します(Unityを使用しない場合、すべて正常に動作します)。
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);
}
}
ありがとう!!
以下は、ASP.NET Identity 2.0でUnityをナイスにプレイするためにしたことです。
RegisterTypes
クラスのUnityConfig
メソッドに次を追加しました。
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());
クラスUnityConfig
に以下の行を追加してみてください:
container.RegisterType<IAuthenticationManager>(
new InjectionFactory(
o => System.Web.HttpContext.Current.GetOwinContext().Authentication
)
);
これは、Identity 2.0でUnityを使用できるようにする完全な構成としても機能します。
container.RegisterType<MyDbContext>(new PerRequestLifetimeManager(), new InjectionConstructor());
// Identity
container.RegisterType<UserManager<User>>(new HierarchicalLifetimeManager());
container.RegisterType<SignInManager<User, string>>(new HierarchicalLifetimeManager());
container.RegisterType<IUserStore<User>, UserStore<User>>(new PerRequestLifetimeManager(), new InjectionFactory(x => new UserStore<User>(GetConfiguredContainer().Resolve<MyDbContext>())));
container.RegisterType<IAuthenticationManager>(new InjectionFactory(x => HttpContext.Current.GetOwinContext().Authentication));
この設定では、UnityにAccountControllerまたはManageControllerタイプを登録する必要はありません。
Unityを使用してすべての依存関係を本当に管理したい場合は、UnityでIAuthenticationManagerも登録してみてください。
container.RegisterType<IAuthenticationManager>(
new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication));
いくつかの小さな適応により、Unityを使用して、Asp.net Identityに必要なすべての依存関係を解決できます。
私はこれに関する素晴らしい投稿を見つけました(私もテストしました):
http://tech.trailmax.info/2014/09/aspnet-identity-and-ioc-container-registration/
評価ではコメントできませんが、Update3のMVCでマークされた回答をuser3849637sに追加するには、一部の関数が更新されたスキャフォールディングでそれを使用するため、ManageControllerも追加する必要があります。
container.RegisterType<ManageController>(new InjectionConstructor());
container.RegisterFactory<IAuthenticationManager>(o => System.Web.HttpContext.Current.GetOwinContext().Authentication);
これにより、OPが投稿した質問に回答します。これは、私のようにGoogleでこれを見つけた人にとっては最新の回答です。 RegisterFactoryは、Unityでこれを行う新しい方法です。