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

时间:2013-12-07 17:01:47

标签: 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");
}

我的问题类似于MVC5 ApplicationUser custom properties,但似乎使用旧版本的Identity,因为IdentityManager类似乎不存在。

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

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

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

另请注意,我的问题比EntityFramework

更加面向身份

12 个答案:

答案 0 :(得分:94)

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

由于我们在这样的一行中创建UserManager这一事实引起了混淆:

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

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

要解决这个问题,我们不应该在一行中创建UserManager ...以下是我的工作方式:

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

然后通过调用

更新用户
manager.UpdateAsync(user);

然后你转到上下文

var ctx = store.context;

然后

ctx.saveChanges();

wahooooooo ......坚持:)

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

答案 1 :(得分:54)

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

示例解决方案:

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);

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

答案 2 :(得分:11)

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

<VirtualHost *:80>
    ServerAdmin xy
    ServerName xyz
    ServerAlias www.xyz

    DocumentRoot  /var/www/sites/xyz

    <Directory /var/www/sites/xyz>
        Options -Indexes +FollowSymLinks +MultiViews
        AllowOverride All
        Require all granted
    </Directory>


    LogLevel warn

</VirtualHost>

<VirtualHost *:80>
    ServerAdmin xy
    ServerName xyz2
    ServerAlias www.xyz2

    DocumentRoot  /var/www/sites/xyz2

    <Directory /var/www/sites/xyz2>
        Options -Indexes +FollowSymLinks +MultiViews
        AllowOverride All
        Require all granted
    </Directory>


    LogLevel warn

</VirtualHost>

答案 3 :(得分:5)

UserManager不起作用,正如@Kevin Junghans所写,

  

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

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

class AspNetUser :IdentityUser

从SqlServerMembership aspnet_Users迁移。并定义了上下文:

public partial class MyContext : IdentityDbContext<AspNetUser>

我为反射和同步代码道歉 - 如果你把它放在异步方法中,使用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();
 }

答案 4 :(得分:3)

在开发使用ASP.NET Identity的SimpleSecurity版本时,我也遇到了使用UpdateAsync的问题。例如,我添加了一项功能,用于重置密码,需要将密码重置令牌添加到用户信息中。起初我尝试使用UpdateAsync,它得到了与你相同的结果。我最终将用户实体包装在存储库模式中并使其工作。你可以查看SimpleSecurity project for an example。在使用ASP.NET Identity之后(文档仍然不存在)我认为UpdateAsync只是将更新提交到上下文,您仍然需要保存它的上下文以提交到数据库。

答案 5 :(得分:3)

我以相同的方式尝试了这个功能,当我调用UserManager.Updateasync方法时,它成功但数据库中没有更新。花了一些时间后,我找到了另一个解决方案来更新aspnetusers表中的数据,该数据如下:

1)您需要创建从UserDbContext类继承的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是您更新后的实体。

希望这会对你有所帮助。

答案 6 :(得分:2)

出色!!!

IdentityResult result = await UserManager.UpdateAsync(user);

答案 7 :(得分:1)

根据您的问题并在评论中注明。

  

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

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

IdentityResult result = await UserManager.UpdateAsync(user);

  • 检查所有字段所需值的约束
  • 检查UserManager是否使用ApplicationUser创建。

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

答案 8 :(得分:0)

这对我有用。我正在使用Identity 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);

答案 9 :(得分:0)

我正在使用新的EF&amp; Identity Core和我有同样的问题,另外我还有这个错误:

  

无法跟踪实体类型的实例,因为另一个实例   已经跟踪了具有相同密钥的这种类型。

使用新的DI模型,我将构造函数的控制器添加到数据库中。

我试图查看与_conext.ChangeTracker.Entries()存在的冲突,并在我的通话中添加AsNoTracking()但未成功。

我只需要更改对象的状态(在本例中为Identity)

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

在没有创建另一个商店或对象和映射的情况下工作。

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

答案 10 :(得分:0)

我正在使用.Net Core 3.1或更高版本。请按照以下解决方案进行操作:

  public class UpdateAssignUserRole
    {
        public string username { get; set; }
        public string rolename { get; set; }
        public bool IsEdit { get; set; }

    }

 private async Task UpdateSeedUsers(UserManager<IdentityUser> userManager, UpdateAssignUserRole updateassignUsername)
        {
            IList<Users> Users = await FindByUserName(updateassignUsername.username);

            if (await userManager.FindByNameAsync(updateassignUsername.username) != null)
            {
                var user = new IdentityUser
                {
                    UserName = updateassignUsername.username,
                    Email = Users[0].Email,
 
                };
                var result = await userManager.FindByNameAsync(updateassignUsername.username);
                if (result != null)
                {
                    IdentityResult deletionResult = await userManager.RemoveFromRolesAsync(result, await userManager.GetRolesAsync(result));
                    if (deletionResult != null)
                    {
                        await userManager.AddToRoleAsync(result, updateassignUsername.rolename);
                    }
                }
            }

        }

答案 11 :(得分:-1)

将以下代码添加到静态构造函数下的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来保存您添加到自定义应用程序用户的额外属性。