web-dev-qa-db-ja.com

ユーザーデータの更新-ASP.NET Identity

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よりもアイデンティティ指向であることに注意してください

68
gldraphael

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

95
stackunderflow

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

私はこれをテストしましたが、動作します。

54
JoshdeVries

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

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

また、ASP.NET Identityを使用する SimpleSecurity のバージョンを開発するときに、UpdateAsyncの使用に問題がありました。たとえば、パスワードリセットトークンをユーザー情報に追加するために必要なパスワードリセットを行う機能を追加しました。最初にUpdateAsyncを使用してみましたが、同じ結果が得られました。リポジトリパターンでユーザーエンティティをラップして、動作するようにしました。 例としてはSimpleSecurityプロジェクト をご覧ください。 ASP.NET Identityをさらに使用した後(ドキュメントはまだ存在しません)、UpdateAsyncは更新をコンテキストにコミットするだけですが、データベースにコミットするにはコンテキストを保存する必要があります。

3
Kevin Junghans

同じ方法で機能を試してみましたが、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は更新されたエンティティです。

これがあなたのお役に立てば幸いです。

3
Ankit Sahrawat

優れた!!!

IdentityResult result = await UserManager.UpdateAsync(user);
2
Max

あなたの質問に基づいており、コメントにも記載されています。

データベース内のユーザー情報を更新する方法を教えてもらえますか?

はい、コードはデータベースへのApplicationUserの更新に適しています。

IdentityResult result = await UserManager.UpdateAsync(user);

  • すべてのフィールドの必須値の制約を確認します
  • UserManagerがApplicationUserを使用して作成されていることを確認します。

UserManager<ApplicationUser> UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));

1
jd4u

私は新しいEF&Identity Coreを使用していますが、同じ問題がありますが、このエラーが追加されています:

同じキーを持つこのタイプの別のインスタンスがすでに追跡されているため、エンティティタイプのインスタンスを追跡できません。

新しいDIモデルでは、コンストラクターのコントローラーのコンテキストをDBに追加しました。

_conext.ChangeTracker.Entries()との競合を確認しようとしましたが、成功せずにAsNoTracking()を呼び出しに追加しました。

オブジェクトの状態(この場合はIdentity)を変更するだけです

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

また、別のストアまたはオブジェクトとマッピングを作成せずに機能しました。

他の誰かが私の2セントに役立つことを願っています。

0
Ivan Paniagua

これは私のために動作します。 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);
0
Yan