【问题标题】:Simple Injector - Value cannot be null. Parameter name: userManager简单注射器 - 值不能为空。参数名称:userManager
【发布时间】:2020-04-21 11:02:56
【问题描述】:

我正在尝试使用 Simple Injector 设置 ASP.NET Identity,但我遇到了一个又一个问题。我想我已经接近了,但现在我收到一条错误消息

值不能为空。

参数名称:userManager

说明:在执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。

异常详细信息:System.ArgumentNullException:值不能为空。 参数名称:userManager

[ArgumentNullException:值不能为空。 参数名称:userManager] Microsoft.AspNet.Identity.Owin.SignInManager2..ctor(UserManager2 userManager, IAuthenticationManager authenticationManager) +81 MCLETC.UI\App_Start\IdentityConfig.cs:42 中的 ILETSB.MCLETC.UI.ApplicationSignInManager..ctor(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) MCLETC.UI.ApplicationSignInManager.Create(IdentityFactoryOptions1 options, IOwinContext context) in MCLETC.UI\App_Start\IdentityConfig.cs:53 Microsoft.AspNet.Identity.Owin.IdentityFactoryProvider1.Create(IdentityFactoryOptions`1 选项,IOwinContext 上下文)+14 Microsoft.AspNet.Identity.Owin.d__5.MoveNext() +89 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)+102 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)+64 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.d__7.MoveNext() +179 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)+102 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)+64 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.d__12.MoveNext() +180 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar) +69 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult ar) +64 System.Web.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +389 System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +50 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +163

我在这里收到错误消息:

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);
    }
}

启动类:

public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app, Container container)
    {
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
        app.CreatePerOwinContext(() => container.GetInstance<ApplicationUserManager>());

        // Nothing modified below (template code)
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            {
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            }
        });            
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
        app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
    }
}

SimpleInjectorInitializer:

public class SimpleInjectorInitializer
{
    /// <summary>Initialize the container and register it as MVC5 Dependency Resolver.</summary>
    public static Container Initialize(IAppBuilder app)
    {
        var container = GetInitializeContainer(app);

        container.Verify();

        DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

        return container;
    }

    private static Container GetInitializeContainer(IAppBuilder app)
    {
        var container = new Container();
        container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

        // IoC for ASP.NET Identity
        container.RegisterInstance(app);

        container.Register<ApplicationUserManager>(Lifestyle.Scoped);
        container.Register(() => 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));
        container.Register<SignInManager<ApplicationUser, string>, ApplicationSignInManager>(Lifestyle.Scoped);
        container.Register(() => container.IsVerifying ? new OwinContext(new Dictionary<string, object>()).Authentication : HttpContext.Current.GetOwinContext().Authentication, Lifestyle.Scoped);

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

        //Register Modules
        BusinessModule.RegisterServices(container);
        WebModule.RegisterServices(container);

        return container;
    }

    private static void InitializeUserManager(ApplicationUserManager manager, IAppBuilder app)
    {
        manager.UserValidator = new UserValidator<ApplicationUser>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };

        //Configure validation logic for passwords
        manager.PasswordValidator = new PasswordValidator()
        {
            RequiredLength = 8,
            RequireNonLetterOrDigit = true,
            RequireDigit = true,
            RequireLowercase = true,
            RequireUppercase = true,
        };

        // Configure user lockout defaults
        manager.UserLockoutEnabledByDefault = true;
        manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
        manager.MaxFailedAccessAttemptsBeforeLockout = 3;

        // 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 it in here.
        manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
        {
            MessageFormat = "Your security code is {0}"
        });
        manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
        {
            Subject = "Security Code",
            BodyFormat = "Your security code is {0}"
        });

        manager.EmailService = new EmailService();
        manager.SmsService = new SmsService();

        var dataProtectionProvider = app.GetDataProtectionProvider();
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
    }
}   

AccountControllerManageController 的设置与此类似:

    private SignInManager<ApplicationUser, string> _signInManager;
    private ApplicationUserManager _userManager;

    public AccountController(ApplicationUserManager userManager, SignInManager<ApplicationUser, string> signInManager)
    {
        _userManager = userManager;
        _signInManager = signInManager;
    } 

我为 ApplicationUserManager 注册了错误吗?

【问题讨论】:

  • 请发布异常的完整堆栈跟踪和异常详细信息以及所有其内部异常。
  • @Steven 谢谢。我刚刚更新了帖子。内部异常只是null
  • 不需要为 AccountController 注入依赖吗?

标签: c# asp.net-mvc simple-injector


【解决方案1】:

如果你分析堆栈跟踪,问题应该会变得清晰:

  • Microsoft.AspNet.Identity.Owin.SignInManager&lt;TUser, TKey&gt; 的构造函数为 userManager 构造函数参数传递了一个 null 值。
  • 通过传递userManager 参数,从应用程序的ILETSB.MCLETC.UI.ApplicationSignInManager 的构造函数调用Microsoft.AspNet.Identity.Owin.SignInManager&lt;TUser, TKey&gt; 构造函数。
  • ILETSB.MCLETC.UI.ApplicationSignInManager 的构造函数是从 ApplicationSignInManager 自己的 Create 方法中调用的。

换句话说,静态ApplicationSignInManager.Create 方法为ApplicationSignInManager 构造函数提供了一个空值。

这是分析能走多远,因为您还没有提供Create 方法的详细信息。

尝试通过放置断点来调试Create 方法,以分析发生了什么以及为什么值为null

【讨论】:

  • 谢谢史蒂文。我更新了帖子以提供 Create 方法,这是自动生成的。我也会尝试调试它。
  • 我最终注释掉了Create 方法,并在StartupConfigureAuth 方法中添加了app.CreatePerOwinContext(() =&gt; container.GetInstance&lt;ApplicationSignInManager&gt;()); 行并删除了app.CreatePerOwinContext&lt;ApplicationSignInManager&gt;(ApplicationSignInManager.Create);。我相信已经解决了。
猜你喜欢
  • 1970-01-01
  • 2014-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-16
  • 2014-05-17
  • 2016-05-14
相关资源
最近更新 更多