c# - UserManager.CreateAsync(user, password) stuck in infinite loop -


i'm trying make simple implementation of iuserstore essentially:

  • use nhibernate
  • save users in single table (no claims/logins)
  • store role names in same table, in nvarchar column (pipe ('|') separated if multiple items).

when run following method:

[fact] public void create_a_user() {     // _session valid nhibernate isession object     using (var userstore = new simpleuserstore<simpleidentityuser>(_session))     using (var usermanager = new usermanager<simpleidentityuser>(userstore))     {         var user = new simpleidentityuser         {             username = "kenny_mccormick",             rolesstr = "admin",         };          var createtask = usermanager.createasync(user, "the_password");          var result = createtask.result; // never finishes...     } } 

the last line never finish executing.

the weird thing usermanager never calls of functions in simpleuserstore; gets stuck before that.

here components defined:

the user class:

public class simpleidentityuser : iuser {     public virtual guid userid { get; set; }     public virtual string passwordhash { get; set; }     public virtual string securitystamp { get; set; }     public virtual string rolesstr { get; set; }     public virtual string username { get; set; }      public virtual string id     {         { return userid.tostring(); }     } } 

the user store:

public class simpleuserstore<tuser> :     iuserpasswordstore<tuser>,     iuserrolestore<tuser>,     iusersecuritystampstore<tuser>     tuser : simpleidentityuser {     // resharper disable once staticfieldingenerictype     private static readonly task emptytask = new task(() => { });      private readonly isession _session;      public simpleuserstore(isession session)     {         _session = session;     }      public task<tuser> findasync(userlogininfo login)     {         return task.fromresult((tuser) null);     }      public task createasync(tuser user)     {         _session.save(user);         return emptytask;     }      public task updateasync(tuser user)     {         // updates (hopefully) saved automatically when current session committed         return emptytask;     }      public task deleteasync(tuser user)     {         _session.delete(user);         return emptytask;     }      public task<tuser> findbyidasync(string userid)     {         tuser user = null;         guid guidid;          if (guid.tryparse(userid, out guidid))             user = _session.get<tuser>(guidid);          return task.fromresult(user);     }      public task<tuser> findbynameasync(string username)     {         tuser user = _session.query<tuser>().singleordefault(u => u.username == username);         return task.fromresult(user);     }      public task setpasswordhashasync(tuser user, string passwordhash)     {         user.passwordhash = passwordhash;         return emptytask;     }      public task<string> getpasswordhashasync(tuser user)     {         return task.fromresult(user.passwordhash);     }      public task<bool> haspasswordasync(tuser user)     {         return task.fromresult(user.passwordhash != null);     }      public void dispose()     {     }      public task addtoroleasync(tuser user, string role)     {         new simplerolemanager<tuser>(user).addrole(role);          return emptytask;     }      public task removefromroleasync(tuser user, string role)     {         new simplerolemanager<tuser>(user).deleterole(role);          return emptytask;     }      public task<ilist<string>> getrolesasync(tuser user)     {         list<string> roles = new simplerolemanager<tuser>(user).getroles().tolist();          return task.fromresult((ilist<string>) roles);     }      public task<bool> isinroleasync(tuser user, string role)     {         return task.fromresult(new simplerolemanager<tuser>(user).isinrole(role));     }      public task setsecuritystampasync(tuser user, string stamp)     {         user.securitystamp = stamp;         return emptytask;     }      public task<string> getsecuritystampasync(tuser user)     {         return task.fromresult(user.securitystamp);     } } 

how manage roles

probably not important, here anyway:

public class simplerolemanager<tuser> tuser : simpleidentityuser {     private const string separator = "|";      private readonly tuser _user;      public simplerolemanager(tuser user)     {         _user = user;     }      public string[] getroles()     {         return (_user.rolesstr ?? string.empty)             .split(separator.tochararray(), stringsplitoptions.removeemptyentries);     }      public bool isinrole(string rolename)     {         return getroles().contains(rolename);     }      public bool addrole(string rolename)     {         var roles = getroles().tolist();          if (roles.contains(rolename))             return false;          roles.add(rolename);         setroles(roles);         return true;     }      public bool deleterole(string rolename)     {         list<string> roles = getroles().tolist();          if (!roles.contains(rolename))             return false;          roles.remove(rolename);         setroles(roles);         return true;     }      private void setroles(ienumerable<string> roles)     {         _user.rolesstr = string.join(separator, roles);     } } 

i have been inspecting usermanager<tuser> class dotpeek, found no obvious causes weird behavior.

what causing this?

your approach async fundamentally broken @ moment, because you're returning same task all operations... , never starting it. don't see "infinite loop" here - see blocking on task can never complete.

it's not clear hope accomplish emptytask task, it's not helping @ moment.

furthermore, it's not clear code asynchronous in aspect, unless _session.save (etc) asynchronous.

you improve things somewhat running tasks, e.g.

public task createasync(tuser user) {     action action = () => _session.save(user);     return task.run(action); } 

... although fact you're blocking on task in calling code makes pointless, too. (it's not clear how compiles @ moment, task doesn't have result property... task<t> does.)

as noted in comments, create new task run synchronously in new thread - using more threads you'd otherwise need, potential benefit of parallelism. doesn't achieve same goals asynchronous database call (where there wouldn't any threads tied save call - task complete when relevant network response returned).

if don't care being asynchronous, can use:

public task createasync(tuser user) {     _session.save(user);     return task.fromresult<object>(null); } 

this synchronously save (just current code does) return completed task (rather task never complete, per current code).


Comments

Popular posts from this blog

c# - How to get the current UAC mode -

postgresql - Lazarus + Postgres: incomplete startup packet -

javascript - Ajax jqXHR.status==0 fix error -