asp.net-mvc profile membership createuser

asp.net mvc - Al usar Membresía y perfil de ASP.NET con MVC, ¿cómo puedo crear un usuario y configurarlo en HttpContext.Current.User?



asp.net-mvc profile (3)

Implementé un objeto de perfil personalizado en el código como lo describe Joel aquí:

¿Cómo asignar valores de perfil?

Sin embargo, no puedo hacer que funcione cuando estoy creando un nuevo usuario. Cuando hago esto:

Membership.CreateUser(userName, password); Roles.AddUserToRole(userName, "MyRole");

el usuario se crea y se agrega a un rol en la base de datos, pero HttpContext.Current.User todavía está vacío, y Membership.GetUser() devuelve un valor nulo, por lo que esto (del código de Joel) no funciona:

static public AccountProfile CurrentUser { get { return (AccountProfile) (ProfileBase.Create(Membership.GetUser().UserName)); } } AccountProfile.CurrentUser.FullName = "Snoopy";

He intentado llamar Membership.GetUser(userName) y configurar las propiedades del perfil de esa manera, pero las propiedades establecidas permanecen vacías, y llamar a AccountProfile.CurrentUser(userName).Save() no pone nada en la base de datos. También he intentado indicar que el usuario es válido y ha iniciado sesión llamando a Membership.ValidateUser , FormsAuthentication.SetAuthCookie , etc., pero el usuario actual sigue siendo nulo o anónimo (según el estado de las cookies de mi navegador).

RESOLVIÓ (EDITADO ADEMÁS, VEA ABAJO): Basado en la explicación de Franci Penov y algunos experimentos más, descubrí el problema. El código de Joel y las variaciones que probé solo funcionarán con un perfil existente. Si no existe ningún perfil, ProfileBase.Create(userName) devolverá un nuevo objeto vacío cada vez que se llame; puede establecer propiedades, pero no se "pegarán" porque se devolverá una nueva instancia cada vez que acceda a ella. La configuración de HttpContext.Current.User en un nuevo GenericPrincipal le proporcionará un objeto Usuario, pero no un objeto Perfil, y ProfileBase.Create(userName) y HttpContext.Current.Profile seguirán apuntando a nuevos objetos vacíos.

Si desea crear un perfil para un usuario recién creado en la misma solicitud, debe llamar a HttpContext.Current.Profile.Initialize(userName, true) . Luego puede rellenar el perfil inicializado y guardarlo, y será accesible en futuras solicitudes por nombre, por lo que el código de Joel funcionará. Solo estoy usando HttpContext.Current.Profile internamente, cuando necesito crear / acceder al perfil inmediatamente después de la creación. En cualquier otra solicitud, uso ProfileBase.Create(userName) , y he expuesto solo esa versión como pública.

Tenga en cuenta que Franci es correcto: si desea crear el usuario (y los roles) y configurarlo como autenticado en el primer viaje de ida y vuelta, y pedirle al usuario que inicie sesión, podrá acceder al perfil de manera mucho más sencilla. a través del código de Joel en la solicitud posterior. Lo que me sorprendió es que los roles están disponibles de forma inmediata en la creación del usuario sin ninguna inicialización, pero el perfil no.

Mi nuevo código de perfil de cuenta:

public static AccountProfile CurrentUser { get { if (Membership.GetUser() != null) return ProfileBase.Create(Membership.GetUser().UserName) as AccountProfile; else return null; } } internal static AccountProfile NewUser { get { return System.Web.HttpContext.Current.Profile as AccountProfile; } }

Creación de nuevos usuarios:

MembershipUser user = Membership.CreateUser(userName, password); Roles.AddUserToRole(userName, "MyBasicUserRole"); AccountProfile.NewUser.Initialize(userName, true); AccountProfile.NewUser.FullName = "Snoopy"; AccountProfile.NewUser.Save();

Acceso posterior:

if (Membership.ValidateUser(userName, password)) { string name = AccountProfile.CurrentUser.FullName; }

Además, gracias a Franci por explicar el ciclo de vida de la autenticación: llamo a FormsAuthentication.SetAuthCookie en mi función de validación, pero estoy devolviendo un bool para indicar el éxito, porque User.Identity.IsAuthenticated no será verdadero hasta la solicitud posterior.

REVISADO: Soy un idiota. La explicación anterior funciona en el caso estrecho, pero no resuelve el problema principal: llamar a CurrentUser devuelve una nueva instancia del objeto cada vez, sea un perfil existente o no. Debido a que se define como una propiedad, no estaba pensando en esto y escribí:

AccountProfile.CurrentUser.FullName = "Snoopy"; AccountProfile.CurrentUser.OtherProperty = "ABC"; AccountProfile.CurrentUser.Save();

que (por supuesto) no funciona. Debería ser:

AccountProfile currentProfile = AccountProfile.CurrentUser; currentProfile.FullName = "Snoopy"; currentProfile.OtherProperty = "ABC"; currentProfile.Save();

Es mi culpa haber pasado por alto este punto básico, pero creo que declarar CurrentUser como una propiedad implica que es un objeto que puede ser manipulado. En su lugar, debe ser declarado como GetCurrentUser() .


Crear un usuario solo lo agrega a la lista de usuarios. Sin embargo, esto no autentica ni autoriza al nuevo usuario para la solicitud actual. También debe autenticar al usuario en el contexto de solicitud actual o para solicitudes posteriores.

Membership.ValidateUser solo validará las credenciales, pero no autentica al usuario para las solicitudes actuales o posteriores. FormsAuthentication.SetAuthCookie establecerá el ticket de autenticación en la secuencia de respuesta, por lo que la siguiente solicitud se autenticará, pero no afecta el estado de la solicitud actual.

La forma más fácil de autenticar al usuario sería llamar a FormsAuthentication.RedirectFromLoginPage (asumiendo que está usando la autenticación de formularios en su aplicación). Sin embargo, este realmente causaría una nueva solicitud HTTP, que autentificará al usuario.

Alternativamente, si necesita continuar con su lógica para procesar la solicitud actual, pero desea que el usuario se autentique, puede crear un GenericPrincipal , asignarle la identidad del nuevo usuario y configurar el HttpContext.User a ese principal.


En primer lugar, gracias a @Jeremy por compartir tus hallazgos. Me ayudaste a ir en la dirección correcta. En segundo lugar, perdon por chocar este viejo post. Esperemos que esto ayude a alguien a conectar los puntos.

La forma en que finalmente conseguí este trabajo fue usar el siguiente método estático dentro de mi clase de perfil:

internal static void InitializeNewMerchant(string username, Merchant merchant) { var profile = System.Web.HttpContext.Current.Profile as MerchantProfile; profile.Initialize(username, true); profile.MerchantId = merchant.MerchantId; profile.Save(); }


Va a tener problemas con este enfoque si habilita la identificación anónima. En lugar de Membership.GetUser (). UserName, sugeriría usar HttpContext.Profile.UserName.

Me gusta esto...

private UserProfile _profile; private UserProfile Profile { get { return _profile ?? (_profile = (UserProfile)ProfileBase.Create(HttpContext.Profile.UserName)); } }

Sugerencia de sombrero: SqlProfileProvider : ¿puede usar Profile.GetProfile () en un proyecto?