我已将自定义字段添加到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
更加面向身份答案 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 = 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来保存您添加到自定义应用程序用户的额外属性。