Identity 2.1、异步编程和更新额外的用户数据
Identity 2.1, asynchronous programming, and updating additional user data
我明白什么是异步编程,但我很难在我的代码中实际实现它。 Identity 2.1 生成 CRUD 方法,我想向其中添加一些代码。如何获取要保存的 LINQ 更新?我需要使用等待吗? AspNetUsers table 更新正常,但不是我的 UserProfiles table:
// POST: /Users/Edit/5 [Bind(Include = "FirstName,LastName,Email,Id,Address,City,State,PostalCode")]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(EditUserViewModel editUser, params string[] selectedRole)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindByIdAsync(editUser.Id);
if (user == null)
{
return HttpNotFound();
}
user.UserName = editUser.Email;
user.Email = editUser.Email;
user.Address = editUser.Address;
user.City = editUser.City;
user.State = editUser.State;
user.PostalCode = editUser.PostalCode;
var userRoles = await UserManager.GetRolesAsync(user.Id);
selectedRole = selectedRole ?? new string[] { };
var result = await UserManager.AddToRolesAsync(user.Id, selectedRole.Except(userRoles).ToArray<string>());
if (!result.Succeeded)
{
ModelState.AddModelError("", result.Errors.First());
return View();
}
result = await UserManager.RemoveFromRolesAsync(user.Id, userRoles.Except(selectedRole).ToArray<string>());
if (!result.Succeeded)
{
ModelState.AddModelError("", result.Errors.First());
return View();
}
//Update Firstname/Lastname
var dbEntry = db.UserProfiles.Single(x => x.UserId == editUser.Id);
dbEntry.FirstName = editUser.FirstName;
dbEntry.LastName = editUser.LastName;
db.SaveChanges();
return RedirectToAction("Index");
}
ModelState.AddModelError("", "Something failed.");
return View();
}
由于我的post被搁置了,让我更详细地解释一下我的问题。 var dbEntry 未在 db.SaveChanges() 上更新。当我单步执行代码时,editUser.FirstName 和 editUser.LastName 确实有一个值。
var dbEntry 确实有要更新的记录。同样,db.SaveChanges() 不保存。
我认为正在发生的事情与异步编程有关。由于该方法是 public async Task Edit()
而不是:
public 动作结果编辑()。更新将使用 public ActionResult Edit().
由于我不习惯异步编程(我正在学习),我如何在此方法中实现 await 以便 var dbEntry 更新?
好吧,它完全回避了这个问题,但是您到底为什么要使用一个单独的实体来跟踪配置文件数据? Identity 存在的主要原因之一是提供一个更可扩展的用户管理系统,这意味着您不必像以前那样使用 ASP.NET 成员资格来尝试添加功能。
public class ApplicationUser : IdentityUser
{
// everything else already here
public string FirstName { get; set; }
public string LastName { get; set; }
}
然后,只需将它与您已经更新的用户实例一起更新即可:
user.UserName = editUser.Email;
user.Email = editUser.Email;
user.Address = editUser.Address;
user.City = editUser.City;
user.State = editUser.State;
user.PostalCode = editUser.PostalCode;
// add these
user.FirstName = editUser.FirstName;
user.LastName = editUser.LastName;
更令人困惑的是 ApplicationUser
已经以这种方式扩展了,因为地址、城市、州和邮政编码不在 IdentityUser
上。那么,为什么你开始以不同的方式处理名字和姓氏信息,我无法理解。
异步方面应该不是问题。 UserManager
的 ApplicationDbContext
是开箱即用的 AutoDetectChangesEnabled == true
配置。您的第二个 DbContext 很可能不是。如果愿意,可以打开它,或者在调用 Save
.
之前明确设置 db.Entry(dbEntry).State = EntityState.Modified
我明白什么是异步编程,但我很难在我的代码中实际实现它。 Identity 2.1 生成 CRUD 方法,我想向其中添加一些代码。如何获取要保存的 LINQ 更新?我需要使用等待吗? AspNetUsers table 更新正常,但不是我的 UserProfiles table:
// POST: /Users/Edit/5 [Bind(Include = "FirstName,LastName,Email,Id,Address,City,State,PostalCode")]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(EditUserViewModel editUser, params string[] selectedRole)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindByIdAsync(editUser.Id);
if (user == null)
{
return HttpNotFound();
}
user.UserName = editUser.Email;
user.Email = editUser.Email;
user.Address = editUser.Address;
user.City = editUser.City;
user.State = editUser.State;
user.PostalCode = editUser.PostalCode;
var userRoles = await UserManager.GetRolesAsync(user.Id);
selectedRole = selectedRole ?? new string[] { };
var result = await UserManager.AddToRolesAsync(user.Id, selectedRole.Except(userRoles).ToArray<string>());
if (!result.Succeeded)
{
ModelState.AddModelError("", result.Errors.First());
return View();
}
result = await UserManager.RemoveFromRolesAsync(user.Id, userRoles.Except(selectedRole).ToArray<string>());
if (!result.Succeeded)
{
ModelState.AddModelError("", result.Errors.First());
return View();
}
//Update Firstname/Lastname
var dbEntry = db.UserProfiles.Single(x => x.UserId == editUser.Id);
dbEntry.FirstName = editUser.FirstName;
dbEntry.LastName = editUser.LastName;
db.SaveChanges();
return RedirectToAction("Index");
}
ModelState.AddModelError("", "Something failed.");
return View();
}
由于我的post被搁置了,让我更详细地解释一下我的问题。 var dbEntry 未在 db.SaveChanges() 上更新。当我单步执行代码时,editUser.FirstName 和 editUser.LastName 确实有一个值。
var dbEntry 确实有要更新的记录。同样,db.SaveChanges() 不保存。
我认为正在发生的事情与异步编程有关。由于该方法是 public async Task Edit()
而不是:
public 动作结果编辑()。更新将使用 public ActionResult Edit().
由于我不习惯异步编程(我正在学习),我如何在此方法中实现 await 以便 var dbEntry 更新?
好吧,它完全回避了这个问题,但是您到底为什么要使用一个单独的实体来跟踪配置文件数据? Identity 存在的主要原因之一是提供一个更可扩展的用户管理系统,这意味着您不必像以前那样使用 ASP.NET 成员资格来尝试添加功能。
public class ApplicationUser : IdentityUser
{
// everything else already here
public string FirstName { get; set; }
public string LastName { get; set; }
}
然后,只需将它与您已经更新的用户实例一起更新即可:
user.UserName = editUser.Email;
user.Email = editUser.Email;
user.Address = editUser.Address;
user.City = editUser.City;
user.State = editUser.State;
user.PostalCode = editUser.PostalCode;
// add these
user.FirstName = editUser.FirstName;
user.LastName = editUser.LastName;
更令人困惑的是 ApplicationUser
已经以这种方式扩展了,因为地址、城市、州和邮政编码不在 IdentityUser
上。那么,为什么你开始以不同的方式处理名字和姓氏信息,我无法理解。
异步方面应该不是问题。 UserManager
的 ApplicationDbContext
是开箱即用的 AutoDetectChangesEnabled == true
配置。您的第二个 DbContext 很可能不是。如果愿意,可以打开它,或者在调用 Save
.
db.Entry(dbEntry).State = EntityState.Modified