En utilisant ASP .NET et des membres Profil avec MVC, comment puis-je créer un utilisateur et le mettre à HttpContext.Current.User?

StackOverflow https://stackoverflow.com/questions/2547290

Question

Je mis en œuvre un objet profil personnalisé dans le code tel que décrit par Joel ici:

Comment assigner des valeurs Profil?

Je ne peux pas le faire fonctionner quand je crée un nouvel utilisateur, cependant. Quand je fais ceci:

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

l'utilisateur est créé et ajouté à un rôle dans la base de données, mais HttpContext.Current.User est encore vide, et Membership.GetUser() renvoie null, donc ce (à partir du code de Joel) ne fonctionne pas:

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

AccountProfile.CurrentUser.FullName = "Snoopy";

Je l'ai essayé d'appeler Membership.GetUser(userName) et la définition des propriétés profil de cette façon, mais les propriétés du jeu restent vides, et appelant AccountProfile.CurrentUser(userName).Save() ne met rien dans la base de données. J'ai aussi essayé indiquant que l'utilisateur est valide et connecté, en appelant Membership.ValidateUser, FormsAuthentication.SetAuthCookie, etc., mais l'utilisateur actuel est encore nulle ou anonyme (en fonction de l'état de mes cookies de votre navigateur).

RESOLU (PLUS ÉDITÉ voir ci-dessous): Sur la base de l'explication de Franci Penov et un peu plus d'expérimentation, j'ai compris la question. le code de Joel et les variations que j'ai essayé ne fonctionne qu'avec un profil existant. Si aucun profil existe, ProfileBase.Create(userName) retourne un nouvel objet vide à chaque fois qu'il est appelé; vous pouvez définir les propriétés, mais ils ne seront pas « coller » parce qu'une nouvelle instance est retourné chaque fois que vous y accédez. Réglage HttpContext.Current.User à une nouvelle GenericPrincipal vous donner un objet utilisateur, mais pas un objet Profil et ProfileBase.Create(userName) et HttpContext.Current.Profile seront toujours pointer vers de nouveaux objets vides.

Si vous voulez créer un profil pour un utilisateur nouvellement créé dans la même demande, vous devez appeler HttpContext.Current.Profile.Initialize(userName, true). Vous pouvez ensuite alimenter le profil initialisé et de l'enregistrer, et il sera accessible sur les futures demandes de nom, ainsi le code de Joel travaillerez. Je suis que à l'aide interne HttpContext.Current.Profile, quand je dois créer / accéder au profil immédiatement lors de la création. Sur toute autre demande, j'utilise ProfileBase.Create(userName), et je l'ai exposé que cette version en tant que public.

Notez que Franci est correcte: Si vous êtes prêt à créer l'utilisateur (et rôles) et le définir comme assermentée le premier aller-retour, et demander à l'utilisateur de se connecter alors, vous pourrez accéder au profil beaucoup plus simplement par le code de Joel à la demande ultérieure. Ce qui me jeté est que les rôles est immédiatement accessible lors de la création de l'utilisateur sans initialisation, mais le profil est pas.

Mon nouveau code AccountProfile:

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

Nouvelle création de l'utilisateur:

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

L'accès ultérieur:

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

D'autres grâce à Franci pour expliquer le cycle de vie d'authentification - J'appelle FormsAuthentication.SetAuthCookie dans ma fonction de validation, mais je retourne un bool pour indiquer le succès, car User.Identity.IsAuthenticated ne sera pas vrai jusqu'à ce que la suite demande.

RÉVISÉE: Je suis un idiot. L'explication ci-dessus fonctionne dans le cas étroit, mais ne résout pas le problème de base: L'appel CurrentUser retourne une nouvelle instance de l'objet à chaque fois, que ce soit un profil existant ou non. Parce qu'il est défini comme une propriété, je ne pensais pas à cela, et écrit:

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

qui (bien sûr) ne fonctionne pas. Il devrait être:

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

Il est de ma faute pour tout donnant sur ce point fondamental, mais je ne pense déclarer CurrentUser comme une propriété implique qu'il est un objet qui peut être manipulé. Au lieu de cela, il devrait être déclaré comme GetCurrentUser().

Était-ce utile?

La solution

Création d'un utilisateur ajoute simplement à la liste des utilisateurs. Toutefois, cela n'authentifie pas ou autoriser le nouvel utilisateur pour la requête en cours. Vous devez également authentifier l'utilisateur dans le contexte de la requête en cours ou pour les demandes ultérieures.

Membership.ValidateUser ne validera les informations d'identification, mais il n'authentification de l'utilisateur pour les demandes en cours ou à venir. FormsAuthentication.SetAuthCookie donnera le ticket d'authentification dans le flux de réponse, de sorte que la prochaine demande sera authentifié, mais il n'affecte pas l'état de la demande actuelle.

La meilleure façon d'authentifier l'utilisateur serait d'appeler FormsAuthentication.RedirectFromLoginPage (en supposant que vous utilisez l'authentification des formulaires dans votre application). Cependant, celui-ci provoqueraient en fait une nouvelle requête HTTP, qui authentifier l'utilisateur.

Par ailleurs, si vous devez continuer votre logique pour le traitement de la demande actuelle, mais que l'utilisateur à authentifier, vous pouvez créer un GenericPrincipal, attribuez-lui l'identité du nouvel utilisateur et définir la HttpContext.User que principale.

Autres conseils

Vous allez rencontrer des problèmes avec cette approche si vous activez anonymousIdentification. Plutôt que Membership.GetUser (). UserName, je suggère d'utiliser HttpContext.Profile.UserName.

Comme ça ...

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

Pointe du chapeau: SqlProfileProvider - pouvez-vous utiliser Profile.GetProfile () dans un projet?

Tout d'abord, merci de partager vos @ Jeremy résultats. Vous m'a aidé à aller dans la bonne direction. En second lieu, désolé pour ce cognant ancien poste. Espérons que cela vous aidera quelqu'un à relier les points.

La façon dont j'ai finalement obtenu ce travail était d'utiliser la méthode statique suivante dans ma classe de profil:

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();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top