Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ApplicationUserManager.Create called on every request

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

like image 406
MDu Avatar asked Nov 17 '15 18:11

MDu


1 Answers

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...

like image 50
James Joyce Avatar answered Oct 18 '22 21:10

James Joyce