web-dev-qa-db-ja.com

MVC5:UserManager.AddToRole(): "ロールへのユーザーの追加エラー:UserIdが見つかりません"?

私はMVC5/EF6を実験し、コードファーストマイグレーションを使用した新しいID認証を試しています。ソリューションのすべてが現在構築中であり、Migrationを追加できますが、VS2013で_update-database_から_package manager console_を実行すると、_Configuration.cs_ファイルが完全に処理されませんテストデータをテーブルに入れ、_Error Adding User to Role: UserId not found_を出力します。

ユーザーIDを明示的に設定し、マネージャーで生成されるようにしてみました(いくつかの例を参照)が、毎回同じエラーメッセージが表示されます。 _#region User & User Roles_ファイルの_Configuration.cs_ファイルでエラーが失敗していることはわかっていますが、理由はわかりません:

_using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using PersonalPortfolio2.Helper;
using PersonalPortfolio2.Models;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Diagnostics;
using System.Linq;

namespace PersonalPortfolio2.Models
{
    public sealed class Configuration : DbMigrationsConfiguration<PersonalPortfolio2.Models.ApplicationDbContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
        }

        protected override void Seed(PersonalPortfolio2.Models.ApplicationDbContext context)
        {
            BlobHelper bh = new BlobHelper();
            //LocationHelper lh = new LocationHelper();
            ApplicationDbContext db = new ApplicationDbContext();

            #region Roles
            try
            {
                List<string> myRoles = new List<string>(new string[] { "Root", "Admin", "Outsider", "Client", "Primary" });
                var RoleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));

                foreach (string r in myRoles)
                {
                    RoleManager.Create(new IdentityRole(r));
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error Create Roles: " + ex.Message);
            }
            #endregion

            #region User & User Roles
            var store = new UserStore<ApplicationUser>(context);
            var manager = new UserManager<ApplicationUser>(store);

            List<ApplicationUser> myUsers = GetTestUsers();
            var passwordHasher = new PasswordHasher();

            foreach (var u in myUsers)
            {
                var userExists = db.Users.Where(a => a.Email == u.Email).FirstOrDefault();
                if (userExists == null)
                {
                    var user = new ApplicationUser
                    {
                        Email = u.Email,
                        PasswordHash = passwordHasher.HashPassword("P@ssword1"),
                        LockoutEnabled = false,
                        Name = u.Name,
                        Position = u.Position,
                        RegisteredDate = DateTime.Now,
                        LastVisitDate = DateTime.Now,
                        OrganizationId = u.OrganizationId,
                        ProfilePictureSrc = u.ProfilePictureSrc,
                    };

                    try
                    {
                        var userCreateResult = manager.Create(user);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("Error Add User: " + ex.Message + "\n" + ex.InnerException);
                    }

                    // Add User to Roles
                    List<string> usersRoles = GetUserRoles(u.Email);
                    bool codeHit = false;
                    foreach (string role in usersRoles)
                    {
                        try
                        {
                            codeHit = true;
                            manager.AddToRole(user.Id, role);
                        }
                        catch (Exception ex)
                        {
                            // ERROR!
                            throw new Exception("Error Adding User to Role: " + ex.Message + "\n" + ex.Data + "\n" + ex.InnerException + "\nName: " + user.Name + "\nEmail: " + user.Email + "\nuser.ID: " + user.Id + "\nu.Id: " + u.Id + "\nRole: " + role + "\nCodeHit: " + codeHit);
                        }
                    }
                }

            }
            #endregion

}

            #region Helpers
            private List<ApplicationUser> GetTestUsers()
            {
                List<ApplicationUser> testUsers = new List<ApplicationUser>
                {
                    new ApplicationUser
                    {
                        Id = "1",
                        Email = "[email protected]",
                        Name = "Admin User",
                        RegisteredDate = System.DateTime.Now,
                        LastVisitDate = System.DateTime.Now,
                        Position = "Site Administrator",
                        PhoneNumber = "1234564321",
                    },
                    new ApplicationUser
                    {
                        Id = "2",
                        Email = "[email protected]",
                        Name = "James Woods",
                        RegisteredDate = System.DateTime.Now,
                        LastVisitDate = System.DateTime.Now,
                        Position = "Software Developer / Web Designer",
                        PhoneNumber = "1234567890",
                    },
                    new ApplicationUser
                    {
                        Id = "3",
                        Email = "[email protected]",
                        Name = "Tyler Perry",
                        RegisteredDate = System.DateTime.Now,
                        LastVisitDate = System.DateTime.Now,
                        Position = "Company Contact",
                        PhoneNumber = "1234567890",
                    }
                };
                return testUsers;
            }


            public List<string> GetUserRoles(string user)
            {
                List<string> myRoles = new List<string>();
                switch (user)
                {
                        //"Root", "Admin", "Outsider", "Client", "Primary"
                    case "[email protected]":
                        myRoles = new List<string>(new string[] { "Root", "Admin" });
                        break;
                    case "[email protected]":
                        myRoles = new List<string>(new string[] { "Admin" });
                        break;
                    case "[email protected]":
                        myRoles = new List<string>(new string[] { "Client", "Outsider" });
                        break;
                    default:
                        myRoles = new List<string>(new string[] {"[user] not found."});
                        break;
                }
                return myRoles;
            }
            #endregion

    }
}
_

誰かが私が見落としているかもしれないものについてここでいくつかの洞察を提供できますか?詳細については、私の現在のcatchステートメントは以下を出力しています:

_Error Adding User to Role: UserId not found.
System.Collections.ListDictionaryInternal

Name: Admin User
Email: [email protected]
user.ID: 1
u.Id: 1
Role: Root
CodeHit: True
_

管理者ユーザーの明示的な_Id = "1",_をコメントアウトすると、_user.ID_および_u.Id_は_ab753316-3d7b-4f98-a13a-d19f7c926976_になります。私はそれが問題であるGetTestUsers()またはGetUserRoles(u.Email)の私のヘルパーメソッドかもしれないと思っていましたが、私の_try/catch_とcodeHitブール変数の間を使用して、問題が確実にmanager.AddToRole(user.Id, role)から発生していることを確認しました。

21

これは、同様の問題が発生した可能性がある人のために残しておきます。まったく同じ「症状」がありました。保存されているパスワードに関連する問題は、構成されたパスワードポリシー(少なくとも1つの大文字、1つの小文字など)に準拠していないことがわかります。

以下のコメントと回答にあるように、一般に、ユーザー作成の制約またはポリシーが守られていない場合、同じ漠然としたエラーメッセージがスローされます。

これには次のものが含まれます。

  • パスワードポリシーが守られていない(これが最も一般的な原因のようです)
  • 空の文字列/ nullとして渡される必須フィールド
  • ユーザー名またはメールの重複

このエラーが発生する原因となる可能性のある問題は、実際にはさまざまです。上記の方法で問題が解決しない場合は、以下をお勧めします。

  1. ソリューション用に設定されたIDプロバイダーのルールとポリシーを理解する
  2. 以下の@Tedの回答に従って、UserManager.Createメソッドにブレークポイントをトレースまたは配置して結果を表示します。これにより、問題の原因が明らかになる可能性があります。
28
CShark

CraftBeerHipsterDudeの答えは、私が持っていたのと同じ状況に対する答えを見つけるのに役立ちました。 AddToRoleが失敗した場合の秘訣は、Usermanager.Create(...)から返された結果を確認することです。例外はスローされない場合がありますが、作成が失敗したことを示す結果が返されます。私の場合は「ユーザー名はすでに存在しています」でした。

一般化するには:以前の操作の結果を確認して、実際のエラーを追跡します。

11
Ted

質問の作成者への回答:UserIdは入力しないでください。エンティティフレームワークに任せてユーザー用に作成します。また、整数として入力しようとしていますが、ロールベースのセキュリティのユーザーのIDは= GUID文字列の形式なので、文字列が必要な列に整数値を追加しようとしても機能しません。

これは私にとっては問題ではありませんでしたが、同じエラーで他にもいくつか問題がありました。

私は何が欠けているのかを理解しようとしましたが、何も問題はありませんでした。

だから私はVSの別のインスタンスをシードコードのデバッガとして使用しました(これは別のスレッドで見つかりました):

    if (System.Diagnostics.Debugger.IsAttached == false)
    System.Diagnostics.Debugger.Launch();

ロールに追加されたときに、ユーザーが実際にIDを持っていることに気付きました。最後に、空のcatchブロックを追加することで回避策を実行できました。誤ったエラーが原因でコードが例外をスローせず、ユーザーは正しいロールに追加されます。

    try
    {
        var newUser = userManager.FindByEmail(superuserToInsert.Email);
        userManager.AddToRole(newUser.Id, "Super users");
    }
    catch 
    {
    }

新しく作成したユーザーをロールに追加しようとする前に、シードはユーザーの作成をロールバックしているように見え、ユーザーはユーザーデータベースに作成されませんでした。

しかし、ロールへの追加の部分を完全に削除すると、ユーザーはデータベースに追加され、少し編集された構成コードの2回目の実行で、ユーザーがロールに追加される可能性があり、これは誤ったエラーであると思いましたスローされます。空のcatchブロックでこの誤ったエラーを無視すると、ユーザー作成のロールバックも無視されるようです(ロールパーツに追加する直前にカーテンの後ろで発生する必要があります)。コード。

それが誰かを助けることを願って

編集:

上記は私の頭痛のほとんどすべてを修正しましたが、作成できなかった約300のアカウントがまだあることに気付きました(ただし、エラーはスローされませんでした)。単純なFULL OUTER JOINと、ソースデータベーステーブルを使用したユーザーデータベースの調査により、「UserName」列と「Email」列の両方の値にダッシュ(-)文字を使用しているユーザーは、ユーザーが作成されなかったと思いました。そうだった。

これは簡単な修正でした。英数字以外の文字を使用するようにユーザーマネージャーを構成するだけです(属性名が「ユーザー名」のみを指しているように見えても、「メール」にも影響します)。

    var userManager = new UserManager<ApplicationUser>(userStore);

    userManager.UserValidator = new UserValidator<ApplicationUser(userManager)
    {
        AllowOnlyAlphanumericUserNames = false,
    }; 

//ミス

5
Mikael Puusaari

シードメソッドでserManagerおよびRoleManagerを使用することは避けます。代わりに、コンテキストのみを使用します。私が使用するものは、ユーザーを作成してロールに割り当てる次のとおりです。

protected override void Seed(DbModelContext context)
{
    if (context == null)
    {
        throw new ArgumentNullException("context", "Context must not be null.");
    }

    const string UserName = "User";
    const string RoleName = "UserRole";

    var userRole = new IdentityRole { Name = RoleName, Id = Guid.NewGuid().ToString() };
    context.Roles.Add(userRole);

    var hasher = new PasswordHasher();

    var user = new IdentityUser
                   {
                       UserName = UserName,
                       PasswordHash = hasher.HashPassword(UserName),
                       Email = "[email protected]",
                       EmailConfirmed = true,
                       SecurityStamp = Guid.NewGuid().ToString()
                   };

    user.Roles.Add(new IdentityUserRole { RoleId = userRole.Id, UserId = user.Id });

    context.Users.Add(user);

    base.Seed(context);
}

Entityクラスはカスタム実装です(IDとしてGUIDを使用したかったため)が、それらはフレームワーククラスから派生しています。これで、適切なフレームワーククラスに変更した場合と同じように機能するはずです。

[〜#〜]編集[〜#〜]

混乱があったため、カスタムクラスを削除してフレームワーククラスに切り替えました。

4
Horizon_Net

これで2日目が節約できました。 @Daffy Punkに感謝します。私の場合、問題はパスワードでした。以前は「abc」でした。

var studentPassword = "abcABC_9";
                        var user = new ApplicationUser { UserName = "abc", Email = [email protected] };
                        var UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
                        var result = await UserManager.CreateAsync(user, studentPassword.ToString());
                        await UserManager.AddToRoleAsync(user.Id, "Student");
0
abdul hameed

私の場合の問題は、IDの代わりにユーザーの(ユーザー名)を使用することです。以下のコードを使用します。

 public async Task<ActionResult> Register(RegisterViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new ApplicationUser { UserName = model.Username, Email = model.Username, workshopId =model.workshopId};
                var rolesList = _context.Roles.ToList();
                string role = rolesList.FirstOrDefault(r => r.Id == model.SelectedRoleId).Name;
                var result = await UserManager.CreateAsync(user, model.Password);

                // Add User to the selected role from the list in .cshtml
                if (result.Succeeded)
                {
                    await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
                    result =await UserManager.AddToRoleAsync(user.Id, role);
                    // For more information on how to enable account confirmation and password reset please visit https://go.Microsoft.com/fwlink/?LinkID=320771
                    // Send an email with this link
                    // string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
                    // var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
                    // await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking <a href=\"" + callbackUrl + "\">here</a>");

                    return RedirectToAction("Index", "Home");
                }
                AddErrors(result);
            }

            // If we got this far, something failed, redisplay form
            return View(model);
        }
0
Fares Ayyad