Actualización de datos de usuario: identidad de ASP.NET

He agregado campos personalizados a la clase ApplicationUser
También creé un formulario a través del cual el usuario puede ingresar / editar los campos.
Sin embargo, por alguna razón, no puedo actualizar los campos en la base de datos.

 [HttpPost] [ActionName("Edit")] [ValidateAntiForgeryToken] public async Task 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"); } 

Mi problema es similar a las propiedades personalizadas de MVC5 ApplicationUser , pero parece que usa una versión anterior de Identity porque la clase IdentityManager no parece existir.

¿Alguien puede guiarme sobre cómo actualizar User información del User en la base de datos?

ACTUALIZACIÓN: si incluyo todos los campos en el formulario de registro, todos los valores se almacenan en el campo apropiado en un nuevo registro de la tabla Users de la base de datos.

No sé hacer cambios en los campos de un usuario existente (fila en la tabla de users ). UserManager.UpdateAsync(user) no funciona.

También tenga en cuenta que mi problema está más orientado a la identidad que EntityFramework

OK … Pasé horas tratando de entender por qué userManager.updateAsync no persistiría en los datos del usuario que editamos … hasta que llegue a la siguiente conclusión:

La confusión surge del hecho de que creamos el UserManager en una línea como esta:

 var manager = new UserManager(new UserStore(new MyDbContext())); 

… luego usamos manager.UpdateAsync( user ); pero eso actualizará al usuario en el contexto, y luego necesitaremos guardar los cambios en el contexto db de la identidad. Entonces, la pregunta es cómo obtener el Identity DBcontext de la manera más fácil.

Para solucionar esto, no deberíamos crear el UserManager en una línea … y así es como lo hago:

 var store = new UserStore(new MyDbContext()); var manager = new UserManager(store); 

luego de actualizar al usuario llamando

 manager.UpdateAsync(user); 

entonces vas al contexto

 var ctx = store.context; 

entonces

 ctx.saveChanges(); 

wahooooooo … persistió 🙂

Espero que esto ayude a alguien que tiró de su cabello por unas horas: P

Si deja null alguno de los campos para ApplicationUser O IdentityUser null, la actualización volverá a tener éxito pero no guardará los datos en la base de datos.

Ejemplo de solución:

 ApplicationUser model = UserManager.FindById(User.Identity.GetUserId()) 

Agregue los campos recién actualizados:

 model.Email = AppUserViewModel.Email; model.FName = AppUserViewModel.FName; model.LName = AppUserViewModel.LName; model.DOB = AppUserViewModel.DOB; model.Gender = AppUserViewModel.Gender; 

Llamar a UpdateAsync

 IdentityResult result = await UserManager.UpdateAsync(model); 

Lo he probado y funciona.

El contexto OWIN le permite obtener el contexto db. Parece que funciona bien hasta ahora, y después de todo, obtuve la idea de la clase ApplciationUserManager que hace lo mismo.

  internal void UpdateEmail(HttpContext context, string userName, string email) { var manager = context.GetOwinContext().GetUserManager(); var user = manager.FindByName(userName); user.Email = email; user.EmailConfirmed = false; manager.Update(user); context.GetOwinContext().Get().SaveChanges(); } 

El UserManager no funcionó, y As @Kevin Junghans escribió:

UpdateAsync solo confirma la actualización del contexto, aún necesita guardar el contexto para que se comprometa con la base de datos

Aquí hay una solución rápida (antes de las nuevas características en ASP.net identity v2) que utilicé en un proyecto de formularios web. los

 class AspNetUser :IdentityUser 

Se migró desde SqlServerMembership aspnet_Users. Y el contexto está definido:

 public partial class MyContext : IdentityDbContext 

Pido disculpas por la reflexión y el código síncrono: si lo pones en un método asíncrono, utiliza await para las llamadas asincrónicas y elimina las tareas y Wait () s. The arg, props, contiene los nombres de las propiedades para actualizar.

  public static void UpdateAspNetUser(AspNetUser user, string[] props) { MyContext context = new MyContext(); UserStore store = new UserStore(context); Task 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(); } 

También tuve problemas al utilizar UpdateAsync al desarrollar una versión de SimpleSecurity que utiliza ASP.NET Identity. Por ejemplo, agregué una función para restablecer la contraseña que necesitaba agregar un token de restablecimiento de contraseña a la información del usuario. Al principio intenté usar UpdateAsync y obtuve los mismos resultados que tú. Terminé envolviendo la entidad de usuario en un patrón de repository y lo puse a funcionar. Puede ver el proyecto SimpleSecurity para ver un ejemplo . Después de trabajar con ASP.NET Identity más (la documentación aún no existe), creo que UpdateAsync solo confirma la actualización del contexto, aún necesita guardar el contexto para que se comprometa con la base de datos.

He intentado la funcionalidad de la misma manera y cuando llamo UserManager.Updateasync método UserManager.Updateasync , tiene éxito pero no hay ninguna actualización en la base de datos. Después de pasar algún tiempo, encontré otra solución para actualizar los datos en la tabla aspnetusers , que es la siguiente:

1) necesitas crear UserDbContext clase UserDbContext heredando de la clase IdentityDbContext como esta:

 public class UserDbContext:IdentityDbContext { public UserDbContext(): base("DefaultConnection") { this.Configuration.ProxyCreationEnabled = false; } } 

2) luego en la información de usuario de la actualización del controlador de cuenta como esta:

 UserDbContext userDbContext = new UserDbContext(); userDbContext.Entry(user).State = System.Data.Entity.EntityState.Modified; await userDbContext.SaveChangesAsync(); 

donde el user es su entidad actualizada.

Espero que esto te ayudará.

¡¡¡Excelente!!!

 IdentityResult result = await UserManager.UpdateAsync(user); 

Basado en su pregunta y también anotado en el comentario.

¿Alguien puede guiarme sobre cómo actualizar la información del usuario en la base de datos?

Sí, el código es correcto para actualizar cualquier ApplicationUser a la base de datos.

IdentityResult result = await UserManager.UpdateAsync(user);

  • Verificar restricciones de todos los valores requeridos del campo
  • Compruebe si UserManager se crea con ApplicationUser.

UserManager UserManager = new UserManager(new UserStore(new ApplicationDbContext()));

Esto funciona para mí Estoy usando Identity 2.0, parece que GetApplicationUser ya no está allí.

  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); 

Estoy usando el nuevo EF & Identity Core y tengo el mismo problema, con la adición de que tengo este error:

La instancia del tipo de entidad no se puede rastrear porque ya se está rastreando otra instancia de este tipo con la misma clave.

Con el nuevo modelo DI agregué el controlador del constructor al contexto de la base de datos.

Traté de ver cuál es el conflicto con _conext.ChangeTracker.Entries() y AsNoTracking() a mis llamadas sin éxito.

Solo necesito cambiar el estado de mi objeto (en este caso, Identidad)

 _context.Entry(user).State = EntityState.Modified; var result = await _userManager.UpdateAsync(user); 

Y funcionó sin crear otra tienda u objeto y mapeo.

Espero que alguien más sea útil a mis dos centavos.

Agregue el siguiente código a su archivo Startup.Auth.cs en el constructor estático:

  UserManagerFactory = () => new UserManager(new UserStore(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 }; 

La línea de código de configuración UserManagerFactory es lo que usa para asociar su DataContext personalizado con el UserManager. Una vez hecho esto, puede obtener una instancia del UserManager en su ApiController y el método UserManager.UpdateAsync (usuario) funcionará porque está usando su DataContext para guardar las propiedades adicionales que ha agregado a su usuario de aplicación personalizado.