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カスタムプロパティ に似ていますが、IdentityManagerクラスが存在しないため、古いバージョンのIdentityを使用しているようです。
誰かがデータベースのUser
情報を更新する方法を教えてもらえますか?
更新:すべてのフィールドを登録フォームに含めると、すべての値がデータベースのUsers
テーブルの新しいレコードの適切なフィールドに保存されます。
既存のユーザーのフィールド(users
テーブルの行)を変更する必要がありません。 UserManager.UpdateAsync(user)
は機能しません。
また、私の問題はEntityFrameworkよりもアイデンティティ指向であることに注意してください
OK ... userManager.updateAsync
が編集したユーザーデータを保持しない理由を理解しようとして数時間を費やしました...次の結論に達するまで:
混乱は、次のようにUserManager
を1行で作成するという事実から生じます。
var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new MyDbContext()));
...次にmanager.UpdateAsync( user );
を使用しますが、それによりコンテキスト内のユーザーが更新され、IDのdbcontextへの変更を保存する必要があります。したがって、質問は、最も簡単な方法でIdentity DBcontextを取得する方法です。
これを解決するために、UserManager
を1行で作成しないでください...
var store = new UserStore<ApplicationUser>(new MyDbContext());
var manager = new UserManager(store);
次に、呼び出してユーザーを更新した後
manager.UpdateAsync(user);
その後、コンテキストに移動します
var ctx = store.context;
それから
ctx.saveChanges();
wahooooooo ...持続:)
これが数時間髪を引っ張った人を助けることを願っています: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;
UpdateAsyncを呼び出す
IdentityResult result = await UserManager.UpdateAsync(model);
私はこれをテストしましたが、動作します。
OWINコンテキストを使用すると、dbコンテキストを取得できます。これまでのところうまく動作しているようで、結局、同じことをする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はコンテキストの更新をコミットするだけですが、データベースにコミットするにはコンテキストを保存する必要があります
これは、Webフォームprojetcで使用した簡単なソリューション(ASP.net identity v2の新機能の前)です。の
class AspNetUser :IdentityUser
SqlServerMembership aspnet_Usersから移行されました。そして、コンテキストが定義されます:
public partial class MyContext : IdentityDbContext<AspNetUser>
リフレクションと同期コードをおaびします。これを非同期メソッドに入れた場合、非同期呼び出しに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();
}
また、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()));
私は新しいEF&Identity Coreを使用していますが、同じ問題がありますが、このエラーが追加されています:
同じキーを持つこのタイプの別のインスタンスがすでに追跡されているため、エンティティタイプのインスタンスを追跡できません。
新しいDIモデルでは、コンストラクターのコントローラーのコンテキストをDBに追加しました。
_conext.ChangeTracker.Entries()
との競合を確認しようとしましたが、成功せずにAsNoTracking()
を呼び出しに追加しました。
オブジェクトの状態(この場合はIdentity)を変更するだけです
_context.Entry(user).State = EntityState.Modified;
var result = await _userManager.UpdateAsync(user);
また、別のストアまたはオブジェクトとマッピングを作成せずに機能しました。
他の誰かが私の2セントに役立つことを願っています。
これは私のために動作します。 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);