Answered by:
how to bind UserManager to new UserStore (Customized)

Question
-
User-1045082127 posted
hello
according to the Overview of Custom Storage Providers for ASP.NET Identity article I was create a customized identity classes in to the new empty project and conduct step by step
but there is a problem in the end of it . that is how to bind the new customized UserStore to the UserManager Classes. Im confused to change and update a App_Start folder sub classes like Startup.Auth and identity config. here I upload a whole project . tnx of any person who review my project and help me to resolve our problems
Thursday, June 21, 2018 9:12 AM
Answers
-
User283571144 posted
Hi aminsoraya,
According to your description and project, I found you have created the custom iuser and iuserstore.
But I found you still use Microsoft.AspNet.Identity.EntityFramework IdentityUser class in the DataContext file.
Please uninstall the Microsoft.AspNet.Identity.EntityFramework IdentityUser.
This will make your custom IdentityUser class not wroking.
Besides, in current identity version, use the string instead of int as the user id.
So if you want to pass the application user to the usermanger, you should modify your user class to string instread of int.
If you want to customized iuserstore, I suggest you could inhert IUserStore<TUser>.
More detials, you could refer to below codes:
IdentityConfig:
using ASPNetIdentity.Models; using ASPNetIdentity.Models.Accounts; using Microsoft.AspNet.Identity.Owin; using Microsoft.Owin; using System; using System.Collections.Generic; using System.Linq; using System.Web; using ASPNetIdentity.Models.Accounts; using Microsoft.AspNet.Identity; using Microsoft.Owin.Security; namespace ASPNetIdentity.App_Start { public class IdentityConfig : SignInManager<ApplicationUser, string> { public IdentityConfig(UserManager<ApplicationUser, string> userManager, IAuthenticationManager authenticationManager) : base(userManager, authenticationManager) { } public static IdentityConfig Create(IdentityFactoryOptions<IdentityConfig> options, IOwinContext context) { return new IdentityConfig(context.GetUserManager<ApplicationUserManager>(), context.Authentication); } } public class ApplicationUserManager : UserManager<ApplicationUser> { public ApplicationUserManager(IUserStore<ApplicationUser> store) : base(store) { } public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) { var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<DataContext>())); // Configure validation logic for usernames manager.UserValidator = new UserValidator<ApplicationUser>(manager) { AllowOnlyAlphanumericUserNames = false, RequireUniqueEmail = true }; // Configure validation logic for passwords manager.PasswordValidator = new PasswordValidator { RequiredLength = 6, RequireNonLetterOrDigit = true, RequireDigit = true, RequireLowercase = true, RequireUppercase = true, }; // Configure user lockout defaults manager.UserLockoutEnabledByDefault = true; manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5); manager.MaxFailedAccessAttemptsBeforeLockout = 5; // 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}" }); var dataProtectionProvider = options.DataProtectionProvider; if (dataProtectionProvider != null) { manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity")); } return manager; } } }
IdentityUser:
using Microsoft.AspNet.Identity; using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace ASPNetIdentity.Models.Accounts { public class IdentityUser:IUser<string> { public IdentityUser() { } public IdentityUser(string userName) { } public string Id { get; set; } public string UserName { get; set; } public string Password { get; set; } public string Email { get; set; } } }
UserStore:
Notice:
You need write the logic to implement the FindByIdAsync and FindByNameAsync
using Microsoft.AspNet.Identity; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Web; namespace ASPNetIdentity.Models.Accounts { public class UserStore<TUser>: IUserStore<TUser> where TUser:IdentityUser { private DataContext Context; public UserStore() { } public UserStore(DataContext Context) { this.Context = Context; } public Task CreateAsync(TUser user) { Context.tbUsers.Add(new tbUser { UserName = user.UserName,/* Password = user.Password,*/ Email = user.Email }); return Task.Run(()=>Context.SaveChangesAsync()); } public Task DeleteAsync(TUser user) { tbUser obj = Context.tbUsers.Where(id=>id.Id==user.Id).SingleOrDefault(); Context.tbUsers.Remove(obj); return Task.Run(()=>Context.SaveChanges()); } public Task<IdentityUser> FindByIdAsync(string userId) { tbUser user = Context.tbUsers.Where(r => r.Id == userId).SingleOrDefault(); IdentityUser Iuser = new IdentityUser() { Id = user.Id, UserName = user.UserName, //Password = user.Password, Email = user.Email }; return Task.Run(()=>Iuser); } public Task<IdentityUser> FindByNameAsync(string userName) { tbUser user = Context.tbUsers.Where(r => r.UserName == userName).SingleOrDefault(); IdentityUser Iuser = new IdentityUser() { Id = user.Id, UserName = user.UserName, //Password = user.Password, Email = user.Email }; return Task.Run(() => Iuser); } public Task UpdateAsync(TUser user) { tbUser obj = Context.tbUsers.Where(id => id.Id == user.Id).SingleOrDefault(); obj = new tbUser (){UserName=user.UserName,/*Password=user.Password,*/Email=user.Email }; Context.Entry(obj).State=System.Data.Entity.EntityState.Modified; return Task.Run(() => Context.SaveChanges()); } public void Dispose() { } public Task<string> GetPasswordHashAsync(IdentityUser user) { string obj = Context.tbUsers.Where(id => id.Password == user.Password).SingleOrDefault().Password ?? ""; return Task.Run(() => obj); } public Task<bool> HasPasswordAsync(TUser user) { bool obj = Context.tbUsers.Where(id => id.Password == user.Password).SingleOrDefault().Password!=null ?true:false; return Task.Run(() => obj); } public Task SetPasswordHashAsync(TUser user, string passwordHash) { tbUser obj = Context.tbUsers.Where(id => id.Id == user.Id).SingleOrDefault(); obj = new tbUser() { Password = user.Password}; Context.Entry(obj).State = System.Data.Entity.EntityState.Modified; return Task.Run(() => Context.SaveChanges()); } Task<TUser> IUserStore<TUser, string>.FindByIdAsync(string userId) { throw new NotImplementedException(); } Task<TUser> IUserStore<TUser, string>.FindByNameAsync(string userName) { throw new NotImplementedException(); } } }
Best Regards,
Brando
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Friday, June 22, 2018 10:08 AM
All replies
-
User283571144 posted
Hi aminsoraya,
According to your description and project, I found you have created the custom iuser and iuserstore.
But I found you still use Microsoft.AspNet.Identity.EntityFramework IdentityUser class in the DataContext file.
Please uninstall the Microsoft.AspNet.Identity.EntityFramework IdentityUser.
This will make your custom IdentityUser class not wroking.
Besides, in current identity version, use the string instead of int as the user id.
So if you want to pass the application user to the usermanger, you should modify your user class to string instread of int.
If you want to customized iuserstore, I suggest you could inhert IUserStore<TUser>.
More detials, you could refer to below codes:
IdentityConfig:
using ASPNetIdentity.Models; using ASPNetIdentity.Models.Accounts; using Microsoft.AspNet.Identity.Owin; using Microsoft.Owin; using System; using System.Collections.Generic; using System.Linq; using System.Web; using ASPNetIdentity.Models.Accounts; using Microsoft.AspNet.Identity; using Microsoft.Owin.Security; namespace ASPNetIdentity.App_Start { public class IdentityConfig : SignInManager<ApplicationUser, string> { public IdentityConfig(UserManager<ApplicationUser, string> userManager, IAuthenticationManager authenticationManager) : base(userManager, authenticationManager) { } public static IdentityConfig Create(IdentityFactoryOptions<IdentityConfig> options, IOwinContext context) { return new IdentityConfig(context.GetUserManager<ApplicationUserManager>(), context.Authentication); } } public class ApplicationUserManager : UserManager<ApplicationUser> { public ApplicationUserManager(IUserStore<ApplicationUser> store) : base(store) { } public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) { var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<DataContext>())); // Configure validation logic for usernames manager.UserValidator = new UserValidator<ApplicationUser>(manager) { AllowOnlyAlphanumericUserNames = false, RequireUniqueEmail = true }; // Configure validation logic for passwords manager.PasswordValidator = new PasswordValidator { RequiredLength = 6, RequireNonLetterOrDigit = true, RequireDigit = true, RequireLowercase = true, RequireUppercase = true, }; // Configure user lockout defaults manager.UserLockoutEnabledByDefault = true; manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5); manager.MaxFailedAccessAttemptsBeforeLockout = 5; // 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}" }); var dataProtectionProvider = options.DataProtectionProvider; if (dataProtectionProvider != null) { manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity")); } return manager; } } }
IdentityUser:
using Microsoft.AspNet.Identity; using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace ASPNetIdentity.Models.Accounts { public class IdentityUser:IUser<string> { public IdentityUser() { } public IdentityUser(string userName) { } public string Id { get; set; } public string UserName { get; set; } public string Password { get; set; } public string Email { get; set; } } }
UserStore:
Notice:
You need write the logic to implement the FindByIdAsync and FindByNameAsync
using Microsoft.AspNet.Identity; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Web; namespace ASPNetIdentity.Models.Accounts { public class UserStore<TUser>: IUserStore<TUser> where TUser:IdentityUser { private DataContext Context; public UserStore() { } public UserStore(DataContext Context) { this.Context = Context; } public Task CreateAsync(TUser user) { Context.tbUsers.Add(new tbUser { UserName = user.UserName,/* Password = user.Password,*/ Email = user.Email }); return Task.Run(()=>Context.SaveChangesAsync()); } public Task DeleteAsync(TUser user) { tbUser obj = Context.tbUsers.Where(id=>id.Id==user.Id).SingleOrDefault(); Context.tbUsers.Remove(obj); return Task.Run(()=>Context.SaveChanges()); } public Task<IdentityUser> FindByIdAsync(string userId) { tbUser user = Context.tbUsers.Where(r => r.Id == userId).SingleOrDefault(); IdentityUser Iuser = new IdentityUser() { Id = user.Id, UserName = user.UserName, //Password = user.Password, Email = user.Email }; return Task.Run(()=>Iuser); } public Task<IdentityUser> FindByNameAsync(string userName) { tbUser user = Context.tbUsers.Where(r => r.UserName == userName).SingleOrDefault(); IdentityUser Iuser = new IdentityUser() { Id = user.Id, UserName = user.UserName, //Password = user.Password, Email = user.Email }; return Task.Run(() => Iuser); } public Task UpdateAsync(TUser user) { tbUser obj = Context.tbUsers.Where(id => id.Id == user.Id).SingleOrDefault(); obj = new tbUser (){UserName=user.UserName,/*Password=user.Password,*/Email=user.Email }; Context.Entry(obj).State=System.Data.Entity.EntityState.Modified; return Task.Run(() => Context.SaveChanges()); } public void Dispose() { } public Task<string> GetPasswordHashAsync(IdentityUser user) { string obj = Context.tbUsers.Where(id => id.Password == user.Password).SingleOrDefault().Password ?? ""; return Task.Run(() => obj); } public Task<bool> HasPasswordAsync(TUser user) { bool obj = Context.tbUsers.Where(id => id.Password == user.Password).SingleOrDefault().Password!=null ?true:false; return Task.Run(() => obj); } public Task SetPasswordHashAsync(TUser user, string passwordHash) { tbUser obj = Context.tbUsers.Where(id => id.Id == user.Id).SingleOrDefault(); obj = new tbUser() { Password = user.Password}; Context.Entry(obj).State = System.Data.Entity.EntityState.Modified; return Task.Run(() => Context.SaveChanges()); } Task<TUser> IUserStore<TUser, string>.FindByIdAsync(string userId) { throw new NotImplementedException(); } Task<TUser> IUserStore<TUser, string>.FindByNameAsync(string userName) { throw new NotImplementedException(); } } }
Best Regards,
Brando
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Friday, June 22, 2018 10:08 AM -
User-1045082127 posted
very well thanks for your exelent answer.
I configured your suggestion and nothing seems bad till Iuse in practical ! I mean when i want to register a user an Object reference not set to an instance of an object. Error was thrown!
public async Task<ActionResult> Register(Controls model) { if (ModelState.IsValid) { try { var user = new ApplicationUser { UserName = model.UserName, Email = model.Email }; var result = await UserManager.CreateAsync(user, model.Password); if (result.Succeeded) { await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); // For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771 // Send an email with this link // string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id); // var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme); // await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>"); return RedirectToAction("Index", "Home"); } AddErrors(result); } catch (Exception err) { } } // If we got this far, something failed, redisplay form return View(model); }
I check out action via break point and every thing are have a values . and in the result view : Enumeration yielded no results
tnx and regard
Saturday, June 23, 2018 3:40 AM -
User283571144 posted
Hi aminsoraya,
Could you please tell me which line show the "Object reference not set to an instance of an object" error?
Does the breakpoint come into the CreateAsync method?
If you could post more details information. it will be more easily for us to understand your issue and find the solution.
Best Regards,
Brando
Monday, June 25, 2018 1:52 AM -
User-1045082127 posted
surely . this snipped of code would cause an error :
var result = await UserManager.CreateAsync(user, model.Password);
Monday, June 25, 2018 3:09 AM