我在带有Identity 2的MVC 5项目中使用Ninject。
对于使用它的其余数据上下文和控制器,我没有依赖注入的问题。
对于使用Identity 2模型的Account控制器,当我尝试登录时,我将获得null UserManager
public class AccountController : Controller
{
private ApplicationUserManager _userManager;
public AccountController()
{
}
public AccountController(ApplicationUserManager userManager)
{
UserManager = userManager;
}
public ApplicationUserManager UserManager {
get
{
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
注入所需依赖项的正确方法是什么?我没有创建自定义UserManager,它是开箱即用的模型,ApplicationUserManager是在App_Start下的IdentityConfig.cs中定义的。
作为旁注:我正在使用Ninject的约定扩展:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind(
x => x.FromThisAssembly()
.SelectAllClasses()
.BindAllInterfaces()
);
感谢。
答案 0 :(得分:2)
我在使用Ninject4.0,MVC5.2.3,Identity2.0和Owin3.0.1时遇到了同样的问题,在这里你应该做好正确的工作。
首先你应该从NuGet获得 Ninject.Web.Common.OwinHost ,因为如果你使用Owin,你想使用NinjectMiddleware。
public partial class StartUp
{
private IKernel kernel = null;
public void Configuration(IAppBuilder app)
{
kernel = CreateKernel();
app.UseNinjectMiddleware(() => kernel);
ConfigureAuth(app);
}
public IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
// TODO: Put any other injection which are required.
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
}
正如您所看到的,我们有一种方法可以注入我们想要的所有服务,在这种情况下,我们必须注入 ApplicationUserManager , IUserStore 和的DbContext 即可。因此,对于 Startup 类中的 RegisterServices ,我们有:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<DbContext>().To<ApplicationDbContext>();
kernel.Bind<IUserStore<User, long>>().To<UserStore<User, Role, long, UserLogin, UserRole, UserClaim>>();
kernel.Bind<ApplicationUserManager>().ToSelf();
}
注意:我使用long insted of string作为Identity上所有键的类型,但是 使用defualt(字符串作为键)应该是相同的。
在包含部分 StartUp 类的 StartUp.Auth.cs 文件中,我们应将 ConfigureAuth 方法更改为:
internal static IDataProtectionProvider DataProtectionProvider
{ get; private set; }
public void ConfigureAuth(IAppBuilder app)
{
DataProtectionProvider = app.GetDataProtectionProvider();
//app.CreatePerOwinContext<ApplicationUserManager(ApplicationUserManager.Create)
app.CreatePerOwinContext<ApplicationUserManager>(
(option, context) => {
var kernl = context.Get<IKernel>();
return kernel.Get<ApplicationUserManager>();
});
//rest of the code
}
注意:我们从 owin 之前获取 ApplicationUserManager ,但现在我们从 Ninject内核获取 。请注意我们为 DataProtectionProvider 创建内部静态属性并从appBuilder设置它,我们将在 IdentityConfig / ApplicationUserManager 中使用此属性。 (稍后见)
现在我们必须更改 ApplicationUserManager ,我们将创建方法中的代码移除到构造函数,只需一个依赖 IUserStore ,这是最后一眼:
public class ApplicationUserManager : UserManager<User,long>
{
public ApplicationUserManager(IUserStore<User,long> store)
:base(store)
{
this.UserValidator = new UserValidator<User, long>(this)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
this.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
var dataProtectionProvider = Startup.DataProtectionProvider;
// this is unchanged
if (dataProtectionProvider != null)
{
IDataProtector dataProtector =
dataProtectionProvider.Create("ASP.NET Identity");
this.UserTokenProvider =
new DataProtectorTokenProvider<User,long>(dataProtector);
}
}
}
最后我们可以在帐户控制器 构造函数中使用 ApplicationUserManager ,如下所示:
public class AccountController : ApiController
{
private ApplicationUserManager UserManager ;
public AccountController(ApplicationUserManager userManager){
UserManager = userManager;
}
// all apis come here
}
答案 1 :(得分:0)
您可以尝试从代码中删除问题中提及的行,并将其替换为以下内容:
public AccountController()
: this(new UserManager<ApplicationUser>(new Microsoft.AspNet.Identity.EntityFramework.UserStore<ApplicationUser>(new ApplicationDbContext())))
{
}
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
public UserManager<ApplicationUser> UserManager { get; private set; }