ApplicationUserManager.Create called on every request
Asked Answered
B

2

17

I'm using asp.net mvc 5 with external provider owin provide (facebook, twitter)

ApplicationUserManager.Create is called on every request. There is a lot of unnecessary stuff for logged in user in there (password validator configuration or sms and email service confguration....)

var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
            // Configure validation logic for usernames
            manager.UserValidator = new UserValidator<ApplicationUser>(manager)
            {
                AllowOnlyAlphanumericUserNames = true,
                RequireUniqueEmail = true
            };

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

Also, i think it has something to do with this

public partial class Startup
    {    
        public void ConfigureAuth(IAppBuilder app)
      // Configure the db context, user manager and signin manager to use a  single instance per request
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
...

What can i do to have this "create" called only when needed. I don't want to instantiate password validator and other stuff in there when not required

Thank you

Barron answered 17/11, 2015 at 18:57 Comment(1)
did you ever find out why? I'm dealing with this also.Guesswarp
W
2

No sure if this is still open, but... I also didn't like the way the ApplicationUserManager was called each time, so I decided to change it to a singleton.

The object's dispose method is automatically called, unless you also pass in a destructor callback when you pass in the create.

So my ApplicationUserManager now looks like this:

public class ApplicationUserManager : UserManager<SmartUser, Guid>
{

    //This manager seems to get re-created on every call! So rather keep a singleton...
    private static ApplicationUserManager _userManager;

    private ApplicationUserManager(IUserStore<SmartUser, Guid> store)
        : base(store)
    {
    }

    internal static void Destroy(IdentityFactoryOptions<ApplicationUserManager> options, ApplicationUserManager manager)
    {
        //We don't ever want to destroy our singleton - so just ignore
    }

    internal static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
    {
        if (_userManager == null)
        {
            lock (typeof(ApplicationUserManager))
            {
                if (_userManager == null)
                    _userManager = CreateManager(options, context);
            }
        }

        return _userManager;
    }

    private static ApplicationUserManager CreateManager(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
    { 
       ... your existing Create code ...
    }
}

And in Startup.Auth, I pass in the Destroy callback

        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create, ApplicationUserManager.Destroy);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

Another option would be to just ignore the "registration code that is called per request" and make the UserStore a singleton....

No downside found yet with this heavier-handed approach...

Wigfall answered 16/6, 2018 at 9:33 Comment(1)
this getting error on logout time. have you verified it?Throw
A
0

Personally, using CreatePerOwinContext is definitely not recommended in this case. You should be only initializing the DbContext, UserManager and SignInManager once, and letting EF and MVC determine when a new context is necessary. MVC 5 and newer uses Dependency Injection (DI) more effectively, thus negating the need to having individual instances per context.

Only when you have code that should be considered critical and require a new context should you do so in that specific section of code, and not site-wide.

Acculturize answered 27/1, 2017 at 17:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.