Aggiornamento dei dati utente – Id quadro ASP.NET

Ho aggiunto campi personalizzati alla class ApplicationUser
Ho anche creato un modulo attraverso il quale l’utente può inserire / modificare i campi.
Tuttavia per qualche motivo non sono in grado di aggiornare i campi nel database.

 [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"); } 

Il mio problema è simile alle proprietà personalizzate di MVC5 ApplicationUser , ma sembra utilizzare una versione precedente di Identity perché la class IdentityManager non sembra esistere.

Qualcuno può guidarmi su come aggiornare le informazioni User nel database?

AGGIORNAMENTO: Se includo tutti i campi nel modulo di registrazione, tutti i valori sono memorizzati nel campo appropriato in un nuovo record della tabella Users dal database.

Non so apportare modifiche ai campi di un utente esistente (riga nella tabella users ). UserManager.UpdateAsync(user) non funziona.

Inoltre, il mio problema è più orientato all’id quadro di EntityFramework

OK … Ho passato ore a cercare di capire perché userManager.updateAsync non avrebbe mantenuto i dati utente che abbiamo modificato … fino a quando non ho raggiunto la seguente conclusione:

La confusione deriva dal fatto che creiamo UserManager in una riga come questa:

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

… quindi usiamo manager.UpdateAsync( user ); ma questo aggiornerà l’utente nel contesto e quindi avremo bisogno di salvare le modifiche al dbcontext dell’id quadro. Quindi, la domanda è come ottenere l’Identity DBcontext nel modo più semplice.

Per risolvere questo, non dovremmo creare UserManager in una riga … ed ecco come lo faccio:

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

quindi dopo aver aggiornato l’utente chiamando

 manager.UpdateAsync(user); 

poi vai nel contesto

 var ctx = store.context; 

poi

 ctx.saveChanges(); 

wahooooooo … persistito 🙂

Spero che questo aiuti qualcuno che ha tirato i capelli per qualche ora: P

Se si lascia uno dei campi per ApplicationUser O IdentityUser null, l’aggiornamento tornerà come riuscito ma non salverà i dati nel database.

Soluzione di esempio:

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

Aggiungi i campi appena aggiornati:

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

Chiama UpdateAsync

 IdentityResult result = await UserManager.UpdateAsync(model); 

Ho provato questo e funziona.

Il contesto OWIN ti consente di ottenere il contesto db. Sembra che stia funzionando bene finora, e dopo tutto, ho avuto l’idea dalla class ApplciationUserManager che fa la stessa cosa.

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

UserManager non ha funzionato, e come @Kevin Junghans ha scritto,

UpdateAsync impegna semplicemente l’aggiornamento nel contesto, è comunque necessario salvare il contesto per il commit nel database

Ecco una soluzione rapida (prima delle nuove funzionalità in ASP.net identity v2) che ho usato in un modulo web projetc. Il

 class AspNetUser :IdentityUser 

È stata eseguita la migrazione da SqlServerMembership aspnet_Users. E il contesto è definito:

 public partial class MyContext : IdentityDbContext 

Mi scuso per il reflection e il codice sincrono – se lo metti in un metodo asincrono, usa await per le chiamate asincrone e rimuovi i task e Wait () s. L’argomento, oggetti di scena, contiene i nomi delle proprietà da aggiornare.

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

Ho anche avuto problemi nell’utilizzo di UpdateAsync durante lo sviluppo di una versione di SimpleSecurity che utilizza l’identity framework di ASP.NET. Ad esempio, ho aggiunto una funzionalità per eseguire una reimpostazione della password necessaria per aggiungere un token di reimpostazione della password alle informazioni dell’utente. All’inizio ho provato ad utilizzare UpdateAsync e ho ottenuto gli stessi risultati di te. Ho finito per avvolgere l’ quadro utente in uno schema di repository e l’ho fatto funzionare. Puoi guardare il progetto SimpleSecurity per un esempio . Dopo aver lavorato con ASP.NET Identity in più (la documentazione è ancora inesistente), penso che UpdateAsync impegna l’aggiornamento solo nel contesto, è comunque necessario salvare il contesto affinché si impegni al database.

Ho provato la funzionalità nello stesso modo e quando richiamo il metodo UserManager.Updateasync , succede ma non c’è nessun aggiornamento nel database. Dopo aver trascorso un po ‘di tempo ho trovato un’altra soluzione per aggiornare i dati nella tabella di aspnetusers che sta seguendo:

1) è necessario creare UserDbContext class UserDbContext dalla class IdentityDbContext questo modo:

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

2) quindi in Account controller aggiorna le informazioni dell’utente in questo modo:

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

dove user è la tua quadro aggiornata.

spero che questo ti possa aiutare.

Eccellente!!!

 IdentityResult result = await UserManager.UpdateAsync(user); 

Basato sulla tua domanda e anche notato nel commento.

Qualcuno può guidarmi su come aggiornare le informazioni utente nel database?

Sì, il codice è corretto per l’aggiornamento di ApplicationUser nel database.

IdentityResult result = await UserManager.UpdateAsync(user);

  • Controlla i vincoli di tutti i valori richiesti del campo
  • Verifica che UserManager sia stato creato utilizzando ApplicationUser.

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

Questo funziona per me. Sto usando Identity 2.0, sembra che GetApplicationUser non sia più lì.

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

Sto usando il nuovo EF & Identity Core e ho lo stesso problema, con l’aggiunta che ho questo errore:

L’istanza del tipo di quadro non può essere tracciata perché un’altra traccia di questo tipo con la stessa chiave è già stata tracciata.

Con il nuovo modello DI ho aggiunto il controller del costruttore al contesto del DB.

Ho provato a vedere quali sono i conflitti con _conext.ChangeTracker.Entries() e aggiungendo AsNoTracking() alle mie chiamate senza successo.

Ho solo bisogno di cambiare lo stato del mio object (in questo caso Identity framework)

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

E ha lavorato senza creare un altro negozio o object e mapping.

Spero che qualcun altro sia utile per i miei due centesimi.

Aggiungi il seguente codice al tuo file Startup.Auth.cs sotto il costruttore statico:

  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 riga di codice UserManagerFactory è ciò che si usa per associare il DataContext personalizzato con UserManager. Dopo averlo fatto, puoi ottenere un’istanza di UserManager nel tuo ApiController e il metodo UserManager.UpdateAsync (utente) funzionerà perché sta utilizzando il tuo DataContext per salvare le proprietà extra che hai aggiunto all’utente dell’applicazione personalizzata.