更新用户数据 – 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)你需要创buildUserDbContext
inheritance自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来保存你添加到你的自定义应用程序用户的额外属性。