更新用户数据 – ASP.NET身份

我已经将自定义字段添加到ApplicationUser
我也创build了一个用户可以input/编辑字段的表单。
但由于某种原因,我无法更新数据库中的字段。

 [HttpPost] [ActionName("Edit")] [ValidateAntiForgeryToken] public async Task<ActionResult> Manage(EditProfileViewModel model) { if (ModelState.IsValid) { // Get the current application user var user = User.Identity.GetApplicationUser(); // Update the details user.Name = new Name { First = model.FirstName, Last = model.LastName, Nickname = model.NickName }; user.Birthday = model.Birthdate; // This is the part that doesn't work var result = await UserManager.UpdateAsync(user); // However, it always succeeds inspite of not updating the database if (!result.Succeeded) { AddErrors(result); } } return RedirectToAction("Manage"); } 

我的问题类似于MVC5 ApplicationUser自定义属性 ,但似乎使用旧版Identity,因为IdentityManager类似乎不存在。

有人可以指导我如何更新数据库中的User信息?

更新:如果我包含registry单中的所有字段,则所有值都将存储在数据库中Users表的新logging的相应字段中。

我不知道要更改现有用户的字段( users表中的行)。 UserManager.UpdateAsync(user)不起作用。

还要注意我的问题是比EntityFramework更多的面向标识

好的…我花了好几个小时试图弄明白为什么userManager.updateAsync不会保留我们编辑的用户数据……直到我得出以下结论:

由于我们在一行中创buildUserManager这样的事实而引起混淆:

 var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new MyDbContext())); 

…然后我们使用manager.UpdateAsync( user ); 但是会在上下文中更新用户,然后我们需要保存对Identity的dbcontext的更改。 所以,问题是如何以最简单的方式获得Identity DBContext。

为了解决这个问题,我们不应该在一行中创buildUserManager …以下是我该如何做的:

 var store = new UserStore<ApplicationUser>(new MyDbContext()); var manager = new UserManager(store); 

然后通过调用更新用户

 manager.UpdateAsync(user); 

那么你去上下文

 var ctx = store.context; 

然后

 ctx.saveChanges(); 

wahooooooo …坚持:)

希望这可以帮助那些拉头发几个小时的人:P

如果将ApplicationUser或IdentityUser的任何字段留空,则更新将成功返回,但不会将数据保存到数据库中。

示例解决scheme

 ApplicationUser model = UserManager.FindById(User.Identity.GetUserId()) 

添加新更新的字段:

 model.Email = AppUserViewModel.Email; model.FName = AppUserViewModel.FName; model.LName = AppUserViewModel.LName; model.DOB = AppUserViewModel.DOB; model.Gender = AppUserViewModel.Gender; 

调用UpdateAsync

 IdentityResult result = await UserManager.UpdateAsync(Model); 

我已经testing了这个,它的工作原理。

OWIN上下文允许你获取数据库上下文。 似乎到目前为止我工作得很好,毕竟,我从ApplciationUserManager类中得到了同样的想法。

  internal void UpdateEmail(HttpContext context, string userName, string email) { var manager = context.GetOwinContext().GetUserManager<ApplicationUserManager>(); var user = manager.FindByName(userName); user.Email = email; user.EmailConfirmed = false; manager.Update(user); context.GetOwinContext().Get<ApplicationDbContext>().SaveChanges(); } 

用户pipe理器没有工作,而作为@凯文Junghans写道,

UpdateAsync只是将更新提交到上下文,您仍然需要保存上下文以提交到数据库

这里是快速的解决scheme(在ASP.net身份v2的新function之前)我用在一个web表单projetc。 该

 class AspNetUser :IdentityUser 

从SqlServerMembership aspnet_Users迁移。 上下文被定义为:

 public partial class MyContext : IdentityDbContext<AspNetUser> 

我为reflection代码和同步代码表示歉意 – 如果你把它放在一个asynchronous方法中,请使用await进行asynchronous调用并删除Tasks和Wait()。 arg,props包含要更新的属性的名称。

  public static void UpdateAspNetUser(AspNetUser user, string[] props) { MyContext context = new MyContext(); UserStore<AspNetUser> store = new UserStore<AspNetUser>(context); Task<AspNetUser> cUser = store.FindByIdAsync(user.Id); cUser.Wait(); AspNetUser oldUser = cUser.Result; foreach (var prop in props) { PropertyInfo pi = typeof(AspNetUser).GetProperty(prop); var val = pi.GetValue(user); pi.SetValue(oldUser, val); } Task task = store.UpdateAsync(oldUser); task.Wait(); context.SaveChanges(); } 

在开发使用ASP.NET标识的SimpleSecurity版本时,我也遇到了使用UpdateAsync的问题。 例如,我添加了一个function来执行密码重置,需要将密码重置令牌添加到用户信息。 起初,我尝试使用UpdateAsync,它得到了和你一样的结果。 我最终将用户实体封装在一个存储库模式中,并使其工作。 你可以看一下SimpleSecurity项目的例子 。 在使用ASP.NET Identity之后(文档仍然不存在),我认为UpdateAsync只是将更新提交给上下文,您仍然需要保存上下文以提交到数据库。

我已经以相同的方式尝试了function,当我调用UserManager.Updateasync方法成功,但在数据库中没有更新。 花了一些时间后,我发现另一个解决scheme来更新aspnetusers表中的数据是这样的:

1)你需要创buildUserDbContextinheritance自IdentityDbContext类的类,如下所示:

 public class UserDbContext:IdentityDbContext<UserInfo> { public UserDbContext(): base("DefaultConnection") { this.Configuration.ProxyCreationEnabled = false; } } 

2)然后在账户控制器更新用户信息是这样的:

 UserDbContext userDbContext = new UserDbContext(); userDbContext.Entry(user).State = System.Data.Entity.EntityState.Modified; await userDbContext.SaveChangesAsync(); 

user是您的更新实体。

希望这会帮助你。

根据你的问题,并在评论中也注意到。

有人可以指导我如何更新数据库中的用户信息?

是的,代码是正确的更新任何ApplicationUser到数据库。

IdentityResult result = await UserManager.UpdateAsync(user);

  • 检查所有字段所需值的限制
  • 检查UserManager是使用ApplicationUser创build的。

UserManager<ApplicationUser> UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));

优秀!!!

 IdentityResult result = await UserManager.UpdateAsync(user); 

这对我有用。 我正在使用身份2.0,看起来像GetApplicationUser不存在了。

  var user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); if (!string.IsNullOrEmpty(form["FirstName"])) { user.FirstName = form["FirstName"]; } if (!string.IsNullOrEmpty(form["LastName"])) { user.LastName = form["LastName"]; } IdentityResult result = await UserManager.UpdateAsync(user); 

我正在使用新的EF和身份核心,我有同样的问题,除了我有这个错误:

实体types的实例不能被跟踪,因为具有相同密钥的这种types的另一个实例已经被跟踪。

使用新的DI模型,我将构造函数的Controller上下文添加到数据库中。

我试图看看是什么与_conext.ChangeTracker.Entries()冲突,并添加AsNoTracking()我的通话没有成功。

我只需要改变我的对象的状态(在这种情况下,身份)

 _context.Entry(user).State = EntityState.Modified; var result = await _userManager.UpdateAsync(user); 

并没有创build另一个商店或对象和映射工作。

我希望别人有用我的两分钱。

将下面的代码添加到静态构造函数下的Startup.Auth.cs文件中:

  UserManagerFactory = () => new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())); OAuthOptions = new OAuthAuthorizationServerOptions { TokenEndpointPath = new PathString("/Token"), Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory), AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"), AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), AllowInsecureHttp = true }; 

UserManagerFactory设置代码行是用来将您的自定义DataContext与UserManager相关联的。 一旦你完成了,那么你可以在你的ApiController中获得UserManager的一个实例,并且UserManager.UpdateAsync(user)方法将工作,因为它使用你的DataContext来保存你添加到你的自定义应用程序用户的额外属性。