wake-up-neo.com

MVC5: UserManager.AddToRole (): "Fehler beim Hinzufügen eines Benutzers zur Rolle: Benutzer-ID nicht gefunden"?

Ich habe mit MVC5/EF6 experimentiert und die neue Identitätsauthentifizierung mit Code-First-Migrationen ausprobiert. Alles in der Lösung wird derzeit erstellt und ich kann eine Migration hinzufügen. Wenn ich jedoch einen update-database über den package manager console in VS2013 durchführe, kann meine Configuration.cs-Datei meine Testdaten nicht vollständig in meine Tabellen und Ausgaben Error Adding User to Role: UserId not found verarbeiten.

Ich habe versucht, eine Benutzer-ID explizit festzulegen und sie vom Manager generieren zu lassen (wie in einigen Beispielen gezeigt), erhalte jedoch jedes Mal die gleiche Fehlermeldung. Ich weiß, dass der Fehler in meinem #region User & User Roles meiner Configuration.cs-Datei fehlschlägt, bin mir aber nicht sicher, warum:

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("[email protected]"),
                        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

    }
}

Kann jemand hier einen Einblick in das gewähren, was ich übersehen habe? Für alle Details gibt meine aktuelle Anweisung catch Folgendes aus:

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

Wenn ich den expliziten Id = "1", für meinen Administrator auskommentiere, werden der user.ID und der u.Id zu: ab753316-3d7b-4f98-a13a-d19f7c926976. Ich hatte geglaubt, es könnten meine Hilfsmethoden für GetTestUsers() oder GetUserRoles(u.Email) sein, aber zwischen meinem try/catch und der von mir verwendeten codeHit booleschen Variablen habe ich festgestellt, dass das Problem definitiv von manager.AddToRole(user.Id, role) herrührt.

19

Ich lasse das hier für alle, die ein ähnliches Problem haben könnten. Ich hatte genau die gleichen "Symptome". Es stellt sich heraus, dass das Problem damit zusammenhängt, dass das Kennwort gespeichert wird und nicht der konfigurierten Kennwortrichtlinie entspricht (mindestens ein Großbuchstabezeichen, ein Kleinbuchstabenzeichen usw.). 

Gemäß den folgenden Kommentaren und Antworten wird im Allgemeinen die gleiche vage Fehlermeldung ausgegeben, wenn die Einschränkungen bei der Benutzererstellung oder die Richtlinien nicht eingehalten werden.

Dies kann Folgendes beinhalten:

  • Passwort-Richtlinie nicht befolgt (dies scheint die häufigste Ursache zu sein)
  • Erforderliche Felder, die als leere Zeichenfolgen/null übergeben werden
  • Doppelter Benutzername oder E-Mail

Es gibt eine Vielzahl von Problemen, die dazu führen können, dass dieser Fehler auftritt. Wenn das oben genannte Problem Ihr Problem nicht löst, empfehle ich Folgendes:

  1. Machen Sie sich mit den Regeln und Richtlinien für den Identitätsanbieter vertraut, die für Ihre Lösung eingerichtet wurden
  2. Verfolgen Sie die Antwort von @ Ted unten und fügen Sie einen Haltepunkt in der UserManager.Create-Methode ein, um das Ergebnis anzuzeigen, da dies wahrscheinlich die Ursache Ihres Problems erkennen lässt.
27
Daffy Punk

Die Antwort von CraftBeerHipsterDude half mir, die Antwort auf dieselbe Situation zu finden, die ich hatte. Wenn AddToRole fehlschlägt, besteht der Trick darin, das von Usermanager.Create (...) zurückgegebene Ergebnis anzuzeigen. Es wird möglicherweise keine Ausnahme ausgelöst, es werden jedoch Ergebnisse zurückgegeben, die besagen, dass die Erstellung fehlgeschlagen ist. In meinem Fall war es "Benutzername existiert bereits".

Zur Verallgemeinerung: Überprüfen Sie die Ergebnisse früherer Operationen, um den tatsächlichen Fehler aufzuspüren.

10
Ted

Antwort auf den Fragenersteller: Die UserId sollte nicht eingegeben werden. Überlassen Sie diese Option dem Entitätsframework, um sie für die Benutzer zu erstellen. Sie versuchen auch, sie als Ganzzahl einzugeben. Die ID für Benutzer mit rollenbasierter Sicherheit ist jedoch ein _.GUID in Form einer Zeichenfolge, daher würde es ohnehin nicht funktionieren, wenn Sie versuchen, einen ganzzahligen Wert für eine Spalte hinzuzufügen, die eine Zeichenfolge erwartet.

Nun war dies nicht das Problem für mich, aber ich hatte ein paar andere Probleme mit dem gleichen Fehler:

Ich versuchte herauszufinden, was mir fehlte, aber ich fand nichts falsches.

Also habe ich eine andere Instanz von VS als Debugger des Seed-Codes verwendet (in einem anderen Thread gefunden):

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

Ich habe festgestellt, dass der Benutzer tatsächlich eine ID hatte, als er zur Rolle hinzugefügt wurde. Am Ende konnte ich eine Problemumgehung durch Hinzufügen eines leeren catch-Blocks durchführen. Der Code löst keine Ausnahmen aufgrund eines falschen Werts aus Fehler und die Benutzer werden zu den richtigen Rollen hinzugefügt:

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

Bevor ich versuchte, einen neu erstellten Benutzer zu einer Rolle hinzuzufügen, schien der Startwert die Erstellung des Benutzers rückgängig zu machen, und der Benutzer wurde nie in der Benutzerdatenbank erstellt.

Als ich das Hinzufügen zum Rollenteil vollständig entfernte, wurde der Benutzer der Datenbank hinzugefügt. Beim zweiten Durchlauf eines etwas bearbeiteten Konfigurationscodes konnte der Benutzer einer Rolle hinzugefügt werden, was mich zu der Annahme führte, dass es ein falscher Fehler war geworfen .. das Ignorieren dieses falschen Fehlers mit dem leeren catch-Block scheint auch das Rollback der Benutzererstellung zu ignorieren (was hinter den Vorhängen unmittelbar vor dem Hinzufügen zum Rollenteil geschehen muss), was dazu führt, dass der Benutzer beim Hinzufügen zum Rollenteil vorhanden ist Code.

Hoffe es hilft jemandem

BEARBEITEN:

Das obige Problem beinahe alle meine Kopfschmerzen, aber ich bemerkte, dass es immer noch etwa 300 Konten gab, die nicht erstellt werden konnten (es wurden jedoch keine Fehler ausgegeben). Ein einfaches FULL OUTER JOIN und eine Überprüfung der Benutzerdatenbank mit der Quelldatenbanktabelle lassen vermuten, dass Benutzer mit einem Bindestrich (-) in den Werten für die Spalten "UserName" und "Email" die Erstellung der Benutzer angehalten haben war der Fall.

Es war eine einfache Lösung, einfach den Benutzermanager so zu konfigurieren, dass er mehr als alphanumerische Zeichen verwendet: (Und obwohl der Attributname nur auf "Benutzernamen" zu verweisen scheint, betrifft dies auch "E-Mail").

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

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

// Miske

5
Mikael Puusaari

Ich würde die Verwendung von UserManager und RoleManager in Ihrer Seed Methode vermeiden. Stattdessen würde ich nur den Kontext verwenden. Etwas, das ich verwende, ist das Folgende, das einen Benutzer erstellt und ihn einer Rolle zuordnet:

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

Die Entity - Klassen sind benutzerdefinierte Implementierungen (da ich GUIDs als IDs verwenden wollte), sie stammen jedoch von den Framework-Klassen. Damit sollte es auf die gleiche Weise funktionieren, wenn Sie sie in die entsprechenden Framework-Klassen ändern.

EDIT

Ich habe die benutzerdefinierten Klassen entfernt und sie auf die Framework-Klassen umgestellt, weil es einige Verwirrung gab.

4
Horizon_Net

Das hat meinen 2. Tag gerettet. Danke @ Daffy Punk. In meinem Fall war das Problem ein Passwort. was vorher "abc" war. 

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

das Problem in meinem Fall ist, dass ich (Benutzername) des Benutzers anstelle von ID, Arbeitscode unten verwenden:

 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