更新用户数据 - ASP.NET标识

gld*_*ael 69 asp.net-mvc asp.net-mvc-5 asp.net-identity

我已经在ApplicationUser课程中添加了自定义字段,
我还创建了一个表单,用户可以通过该表单输入/编辑字段.
但由于某种原因,我无法更新数据库中的字段.

[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");
}
Run Code Online (Sandbox Code Playgroud)

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

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

更新:如果我在寄存器表单中包含所有字段,则所有值都存储在Users数据库表中新记录的相应字段中.

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

另请注意,我的问题比EntityFramework更加面向身份

sta*_*low 96

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

混淆起因于我们UserManager在一行中创建如下:

var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new MyDbContext()));
Run Code Online (Sandbox Code Playgroud)

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

为了解决这个问题,我们不应该UserManager在一行中创建......这就是我如何做到的:

var store = new UserStore<ApplicationUser>(new MyDbContext());
var manager = new UserManager(store);
Run Code Online (Sandbox Code Playgroud)

然后通过调用更新用户

manager.UpdateAsync(user);
Run Code Online (Sandbox Code Playgroud)

然后你去上下文

var ctx = store.context;
Run Code Online (Sandbox Code Playgroud)

然后

ctx.saveChanges();
Run Code Online (Sandbox Code Playgroud)

wahooooooo ...坚持:)

希望这能帮助那些拔头发几个小时的人:P

  • 最后两步的快捷方式:store.context.saveChanges(); (4认同)
  • 最后......对于那些需要全面实施的人来说,这个链接非常好http://weblogs.asp.net/imranbaloch/archive/2013/12/12/a-simple-implementation-of-microsoft-aspnet-identity.aspx (3认同)
  • 我认为调用updateAsync然后两行保存上下文更改是错误的.这不会出现竞争条件吗? (2认同)

小智 54

如果您将ApplicationUser或IdentityUser的任何字段保留为null,则更新将返回成功但不会将数据保存在数据库中.

示例解决方案

ApplicationUser model = UserManager.FindById(User.Identity.GetUserId())
Run Code Online (Sandbox Code Playgroud)

添加新更新的字段:

model.Email = AppUserViewModel.Email;
model.FName = AppUserViewModel.FName;
model.LName = AppUserViewModel.LName;
model.DOB = AppUserViewModel.DOB;
model.Gender = AppUserViewModel.Gender;
Run Code Online (Sandbox Code Playgroud)

调用UpdateAsync

IdentityResult result = await UserManager.UpdateAsync(model);
Run Code Online (Sandbox Code Playgroud)

我测试了这个并且它有效.


Att*_*ers 12

OWIN上下文允许您获取db上下文.到目前为止似乎工作得很好,毕竟,我从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();
    }
Run Code Online (Sandbox Code Playgroud)

  • 我不认为最后一行是不再需要的(当Identity是新的时候会问这个问题).我刚刚检查了一个最近项目的源代码控制,并注意到我只是"等待UserManager.UpdateAsync(user)"并且更改仍然存在.能否请你确认? (3认同)

sub*_*sci 5

UserManager没有用,正如@Kevin Junghans所写,

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

这是我在web表单projetc中使用的快速解决方案(在ASP.net身份v2中的新功能之前).该

class AspNetUser :IdentityUser
Run Code Online (Sandbox Code Playgroud)

是从SqlServerMembership aspnet_Users迁移的.并定义了上下文:

public partial class MyContext : IdentityDbContext<AspNetUser>
Run Code Online (Sandbox Code Playgroud)

我为反射和同步代码道歉 - 如果你把它放在异步方法中,await用于异步调用并删除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();
 }
Run Code Online (Sandbox Code Playgroud)