Обновление пользовательских данных - ASP.NET идентичность
я добавил пользовательские поля к 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) не работает.
также обратите внимание, что моя проблема больше ориентирована на личность, чем EntityFramework
11 ответов:
ОК... Я часами пытался понять, почему
userManager.updateAsyncне будет сохраняться пользовательские данные, которые мы редактируем ... пока я не пришел к следующему выводу:путаница возникает из-за того, что мы создаем
UserManagerв одну строчку:var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new MyDbContext()));...тогда мы используем
manager.UpdateAsync( user );но это обновит пользователя в контексте, а затем нам нужно будет сохранить изменения в dbcontext идентификатора. Итак, вопрос в том, как получить идентификатор 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
Если вы оставите любое из полей для 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);Я проверил это, и это работает.
контекст 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(); }
UserManager не работал, и как писал @Kevin Junghans,
UpdateAsync просто фиксирует обновление в контексте, вам все равно нужно сохранить контекст для его фиксации в базе данных
вот быстрое решение (до появления новых функций в ASP.net identity v2) я использовал в веб-формах projetc. Элемент
class AspNetUser :IdentityUserбыл перенесен из SqlServerMembership aspnet_Users. И контекст определяется:
public partial class MyContext : IdentityDbContext<AspNetUser>приношу свои извинения отражение и синхронный код--если вы помещаете это в асинхронный метод, используйте
awaitдля асинхронных вызовов и удаления задач и ожидания()s. 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(); }
У меня также были проблемы с использованием UpdateAsync при разработке версии SimpleSecurity который использует ASP.NET личность. Например, я добавил функцию для сброса пароля, которая должна была добавить маркер сброса пароля к пользовательской информации. Сначала я попытался использовать UpdateAsync, и он получил те же результаты, что и вы. Я закончил тем, что обернул объект user в шаблон репозитория и заставил его работать. Вы можете посмотреть на проект SimpleSecurity для примера. После работа с ASP.NET Identity more (документация все еще не существует) я думаю, что 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- это ваше обновление сущность.надеюсь, что это поможет вам.
на основе вашего вопроса, а также отметил в комментарии.
может кто-то направить меня о том, как обновить сведения о пользователе в базе данных?
Да, код верен для обновления любого
ApplicationUserв базу данных.
IdentityResult result = await UserManager.UpdateAsync(user);
- Проверьте ограничения всех обязательных значений поля
- проверка для UserManager создается с помощью ApplicationUser.
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);и работал без создания другого магазина или объекта и отображения.
Я надеюсь, что кто-то еще пригодятся мои два цента.
добавьте следующий код в свой стартап.Автор.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. Как только вы это сделаете, то вы можете получить экземпляр класса UserManager в ApiController и класса UserManager.Метод UpdateAsync (user) будет работать, потому что он использует ваш DataContext для сохранения дополнительных свойств, добавленных в пользовательское приложение пользователь.
Comments