我已将自定义字段添加到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自定义属性,但这似乎使用旧版本的Identity,因为IdentityManager类似乎不存在。
有人可以指导我如何更新数据库中User
信息吗?
更新:如果我在注册表单中包含所有字段,则所有值都存储在数据库中Users
表的新记录中的相应字段中。
我不知道要更改现有用户的字段(users
表中的行(。 UserManager.UpdateAsync(user)
不起作用。
另请注意,我的问题比实体框架更面向身份
好的...我花了几个小时试图弄清楚为什么userManager.updateAsync
不会保留我们编辑的用户数据......直到我得出以下结论:
混淆源于我们在一行中创建UserManager
,如下所示:
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new MyDbContext()));
。然后我们使用manager.UpdateAsync( user );
但这将更新上下文中的用户,然后我们需要将更改保存到 Identity 的 dbcontext。因此,问题是如何以最简单的方式获取身份数据库上下文。
为了解决这个问题,我们不应该在一行中创建UserManager
......这是我的做法:
var store = new UserStore<ApplicationUser>(new MyDbContext());
var manager = new UserManager(store);
然后在通过调用更新用户后
manager.UpdateAsync(user);
然后你转到上下文
var ctx = store.context;
然后
ctx.saveChanges();
呜...持久:)
希望这能帮助那些拉头发几个小时的人:P
如果保留 ApplicationUser OR 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;
调用更新异步
IdentityResult result = await UserManager.UpdateAsync(model);
我已经对此进行了测试,并且有效。
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();
}
用户管理器不起作用,正如荣汉斯@Kevin所写,
UpdateAsync 只是将更新提交到上下文,您仍然需要保存上下文以将其提交到数据库
这是我在 Web 表单项目中使用的快速解决方案(在 ASP.net 标识 v2 中的新功能之前(。这
class AspNetUser :IdentityUser
是从 SqlServerMembership aspnet_Users 迁移而来的。上下文被定义:
public partial class MyContext : IdentityDbContext<AspNetUser>
对于反射和同步代码,我深表歉意 - 如果您将其放在异步方法中,请使用await
进行异步调用并删除任务和Wait((s。参数 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 Identity的SimpleSecurity版本时也遇到了使用UpdateAsync的问题。例如,我添加了一项功能来执行密码重置,该功能需要向用户信息添加密码重置令牌。起初我尝试使用UpdateAsync,它得到了与您相同的结果。我最终将用户实体包装在存储库模式中并使其工作。 您可以查看 SimpleSecurity 项目作为示例。在更多地使用 ASP.NET Identity(文档仍然不存在(之后,我认为UpdateAsync只是将更新提交到上下文中,您仍然需要保存上下文以将其提交到数据库。
我以相同的方式尝试了该功能,当我调用该方法时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
是更新的实体。
希望这对你有帮助。
优秀!!
IdentityResult result = await UserManager.UpdateAsync(user);
根据您的问题并在评论中注明。
有人可以指导我如何更新数据库中的用户信息吗?
是的,该代码对于更新数据库的任何ApplicationUser
是正确的。
IdentityResult result = await UserManager.UpdateAsync(user);
- 检查所有字段所需值的约束
- 检查用户管理器是使用应用程序用户创建的。
UserManager<ApplicationUser> UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
我有用。我正在使用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);
我正在使用新的EF和Identity Core,但我遇到了同样的问题,另外我遇到了这个错误:
无法跟踪实体类型的实例,因为另一个实例 具有相同密钥的此类型已被跟踪。
使用新的 DI 模型,我将构造函数的控制器上下文添加到数据库中。
我试图看看与_conext.ChangeTracker.Entries()
有什么冲突,并在我的电话中添加AsNoTracking()
,但没有成功。
我只需要更改对象的状态(在本例中为标识(
_context.Entry(user).State = EntityState.Modified;
var result = await _userManager.UpdateAsync(user);
并且无需创建另一个商店或对象和映射即可工作。
我希望别人对我的两分钱有用。
将以下代码添加到静态构造函数下的 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 来保存您添加到自定义应用程序用户的额外属性。
我使用的是.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);
}
}
}
}