使用ASP.NET MVC5,EF6& Ninject as Backend,AngularJS作为基于令牌的auth(JWT)的前端。
我们最近必须在用户名中启用@chars。基于Startup.cs中的this answer(由Ninject注册码调用,见下文),我们更换了
UserManagerFactory = () => new ApplicationUserManager(new UserStore<IdentityUser>(new SecurityDbContext()));
与
var userManager = new ApplicationUserManager(new UserStore<IdentityUser>(new SecurityDbContext()));
var validator = new UserValidator<IdentityUser>(userManager)
{
AllowOnlyAlphanumericUserNames = false
};
userManager.UserValidator = validator;
UserManagerFactory = () => userManager;
这允许用@符号注册用户名。但是,登录到应用程序(即使使用“普通”用户名)也会出现错误:虽然服务器启动后的第一次登录正常工作,但任何后续登录都会产生以下异常:
Cannot access a disposed object.
Object name: 'ApplicationUserManager'.
详细错误消息:
Source Error: Line 18: public override async Task FindAsync(string userName, string password) Line 19: { Line 20: var result = await base.FindAsync(userName, password); Line 21: if (result == null) Line 22: { Source File: xyz\Infrastructure\ApplicationUserManager.cs Line: 20 Stack Trace: [ObjectDisposedException: Cannot access a disposed object.Object name: 'ApplicationUserManager'.] Microsoft.AspNet.Identity.UserManager`1.ThrowIfDisposed() +99 Microsoft.AspNet.Identity.d__15.MoveNext() +128 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +24 xyz.Infrastructure.d__0.MoveNext() in xzy\Infrastructure\ApplicationUserManager.cs:20 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +24 xyz.Infrastructure.d__0.MoveNext() in xyz\Infrastructure\ApplicationOAuthProvider.cs:39 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52 System.Runtime.CompilerServices.TaskAwaiter.GetResult() +21 Microsoft.Owin.Security.OAuth.d__3a.MoveNext() +862 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +24 Microsoft.Owin.Security.OAuth.d__1e.MoveNext() +2335 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52 System.Runtime.CompilerServices.TaskAwaiter.GetResult() +21 Microsoft.Owin.Security.OAuth.d__0.MoveNext() +1728 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52 System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() +24 Microsoft.Owin.Security.Infrastructure.d__0.MoveNext() +664 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52 System.Runtime.CompilerServices.TaskAwaiter.GetResult() +21 Microsoft.Owin.Security.Infrastructure.d__0.MoveNext() +937 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +93 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +52 System.Runtime.CompilerServices.TaskAwaiter.GetResult() +21 Microsoft.Owin.Security.Infrastructure.d__0.MoveNext() +937 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() +22 Microsoft.Owin.Host.SystemWeb.Infrastructure.ErrorState.Rethrow() +33 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar) +150 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult ar) +42 System.Web.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +415 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
我想这与Ninject有关,所以这里有更多背景:上面改变的代码是从NinjectWebCommon.cs调用的:
kernel.Bind<IUserService>()
.To<UserService>()
.WithConstructorArgument("userManager", Startup.UserManagerFactory());
答案 0 :(得分:3)
问题:这是对象生命周期错误。
解决方案:使用以下代码替换您的代码。
UserManagerFactory = () =>
{
var userManager = new ApplicationUserManager(new UserStore<IdentityUser>(new SecurityDbContext()));
var validator = new UserValidator<IdentityUser>(userManager)
{
AllowOnlyAlphanumericUserNames = false
};
userManager.UserValidator = validator;
return userManager;
};
<强>解释强>
IUserService
时,Ninject就会继续,并希望构建一个新的UserService
。UserService(IUserManager userManager)
构造函数,因此Ninject会按照配置调用Startup.UserManagerFactory()
。UserManagerFactory
是一个lambda表达式,它返回捕获的变量userManager
。这将始终是相同的实例。Dispose
。