c# - tutorial - mvc 5 entity framework relationships
MVC5: UserManager.AddToRole(): “Error al agregar el usuario a la función: ¿No se encontró el UserId”? (5)
Dejo esto aquí para cualquiera que haya tenido un problema similar. Tenía exactamente los mismos "síntomas". Resulta que el problema relacionado con la contraseña que se está almacenando no se adhiere a la política de contraseña configurada (al menos una letra mayúscula, una letra minúscula, etc.).
Según los siguientes comentarios y respuestas, en general, se emite el mismo mensaje de error vago cuando no se cumple alguna de las restricciones o políticas de creación de usuarios.
Esto podría incluir lo siguiente:
- Política de contraseña no seguida (esta parece ser la causa más común)
- Campos obligatorios que se pasan a través de cadenas vacías / null
- Duplicar nombre de usuario o correo electrónico
Realmente hay una amplia gama de problemas que pueden causar este error. Si lo anterior no resuelve su problema, sugiero lo siguiente:
- Familiarícese con las reglas y políticas para el proveedor de identidad tal como se configuró para su solución
- Según la respuesta de @ Ted a continuación, trace o coloque un punto de interrupción en el método UserManager.Create para ver el resultado, ya que esto probablemente revelará la causa de su problema.
He estado experimentando con MVC5 / EF6 y probando la nueva autenticación de identidad con las migraciones de Code-First. Todo lo que hay en la solución se está construyendo actualmente y puedo agregar una Migration
, pero cuando realizo una update-database
través de la package manager console
en VS2013, mi archivo Configuration.cs
falla al procesar completamente mis datos de prueba en mis Tablas y salidas Error Adding User to Role: UserId not found
.
He intentado establecer explícitamente un ID de usuario y dejar que lo genere el Administrador (como se ve en algunos ejemplos), pero cada vez recibo el mismo mensaje de error. Sé que el error está fallando en el #region User & User Roles
de mi archivo Configuration.cs
, pero no estoy seguro de por qué:
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
}
}
¿Alguien puede ofrecer alguna información aquí con lo que puedo estar pasando por alto? Para detalles completos, mi estado actual de catch
está generando lo siguiente:
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
Cuando comento el Id = "1",
explícito Id = "1",
para mi usuario administrador, el user.ID
y u.Id
convierte en: ab753316-3d7b-4f98-a13a-d19f7c926976
. Pensé que podrían ser mis métodos de ayuda los métodos GetTestUsers()
o GetUserRoles(u.Email)
, pero entre mi try/catch
y la variable boolean codeHit
que estoy usando, he verificado que el problema definitivamente proviene del manager.AddToRole(user.Id, role)
.
Esto salvó mi segundo día. Gracias @Daffy Punk. En mi caso el problema fue la contraseña. que era "abc" antes.
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");
La respuesta de CraftBeerHipsterDude me ayudó a encontrar la respuesta a la misma situación que tuve. Si AddToRole falla, el truco es mirar el resultado devuelto por Usermanager.Create (...). Es posible que no se produzca una excepción, pero aún así se muestren resultados que indican que la creación falló. En mi caso era "El nombre de usuario ya existe".
Para generalizar: verifique los resultados de las operaciones anteriores para rastrear el error real.
Respuesta al creador de la pregunta: No se debe ingresar el Id. De usuario, deje eso al marco de la entidad para crearlo para los usuarios. También está tratando de ingresarlo como un entero, pero la identificación de los usuarios en seguridad basada en roles es un GUID en la forma de una cadena, por lo que no funcionaría de todos modos intentar agregar un valor entero para una columna que espera una cadena.
Ahora, este no fue el problema para mí, pero tuve un par de otros problemas con el mismo error:
Traté de averiguar lo que me faltaba, pero no encontré nada malo.
Así que utilicé otra instancia de VS como depurador del código semilla (encontré esto en otro hilo):
if (System.Diagnostics.Debugger.IsAttached == false)
System.Diagnostics.Debugger.Launch();
Noté que el usuario sí tenía una identificación cuando se estaba agregando al rol. Al final pude hacer una solución agregando un bloque catch vacío ... el código no produce excepciones debido a un error falso y los usuarios se agregan a las funciones correctas:
try
{
var newUser = userManager.FindByEmail(superuserToInsert.Email);
userManager.AddToRole(newUser.Id, "Super users");
}
catch
{
}
Antes de intentar agregar un usuario recién creado a un rol, la semilla parecía deshacer la creación del usuario y el usuario nunca se creó en la base de datos de usuarios.
Pero cuando eliminé por completo la parte de agregar a la función, el usuario fue agregado a la base de datos, y en la segunda ejecución de un código de configuración editado un poco, el usuario podría agregarse a una función, lo que me lleva a pensar que fue un error falso. arrojado ... ignorar este error falso con el bloque catch falso parece ignorar también la reversión de la creación del usuario (que debe suceder detrás de las cortinas justo antes de agregar la parte del rol), lo que lleva al usuario a la existencia cuando se agrega al rol parte de la código.
Espero que ayude a alguien
EDITAR:
Lo anterior solucionó casi todo el dolor de cabeza, pero noté que todavía había unas 300 cuentas que no se podían crear (pero no se arrojaron errores). Un simple COMPLETO EXTERNO COMPLETO y un examen de la base de datos de usuarios con la tabla de la base de datos de origen me llevó a pensar que los usuarios con un guión (-) en el valor de las columnas "Nombre de usuario" y "Correo electrónico" impidieron que los usuarios se crearan, y esto fue el caso
Fue una solución fácil, simplemente configure el administrador de usuarios para que use más de caracteres alfanuméricos: (y aunque el nombre del atributo parece apuntar a solo "Nombres de usuario" también afectó al "Correo electrónico")
var userManager = new UserManager<ApplicationUser>(userStore);
userManager.UserValidator = new UserValidator<ApplicationUser(userManager)
{
AllowOnlyAlphanumericUserNames = false,
};
// Miske
Evitaría usar UserManager y RoleManager en su método Seed . En su lugar solo usaría el contexto. Algo que uso es lo siguiente que crea un usuario y le asigna un rol:
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);
}
Las clases de Entidad son implementaciones personalizadas (porque quería usar GUID como ID), pero derivan de las clases de marco. Con eso debería funcionar de la misma manera si los cambias a las clases de marco apropiadas.
EDITAR
Quité las clases personalizadas y las cambié a las clases marco, porque había cierta confusión.