Utilisation ASP.NET adhésion et profil avec MVC, Comment puis-je créer un utilisateur et le configurer à HttpContext.Actuel.Utilisateur?

j'ai implémenté un objet de profil personnalisé dans le code tel que décrit par Joel ici:

comment attribuer des valeurs de profil?

je ne peux pas le faire fonctionner lorsque je crée un nouvel utilisateur, cependant. Lorsque 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 toujours vide, et Membership.GetUser() renvoie null, donc ceci (du code de Joel) ne fonctionne pas:

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

AccountProfile.CurrentUser.FullName = "Snoopy";

j'ai essayé d'appeler Membership.GetUser(userName) et définir les propriétés du profil de cette façon, mais les propriétés restent vides, et appeler AccountProfile.CurrentUser(userName).Save() ne met rien dans la base de données. J'ai aussi essayé d'indiquer que l'utilisateur est valide & connecté, en appelant Membership.ValidateUser,FormsAuthentication.SetAuthCookie, etc., mais l'utilisateur actuel est toujours nul ou anonyme (selon l'état de mon navigateur cookies).

SOLVED (EDITED FURTHER, SEE BELOW): D'après L'explication de Franci Penov et d'autres expérimentations, j'ai résolu le problème. Le code de Joel et les variantes que j'ai essayées ne fonctionneront qu'avec un profil existant. Si aucun Profil n'existe, ProfileBase.Create(userName) retournera un nouvel objet vide à chaque fois qu'il est appelé; vous pouvez définir des propriétés, mais elles ne "colleront" pas parce qu'une nouvelle instance est retournée chaque fois que vous y accédez. Réglage HttpContext.Current.User pour un nouveau GenericPrincipal vous donner un objet Utilisateur, mais un objet Profile, et ProfileBase.Create(userName) et HttpContext.Current.Profile pointera toujours vers de nouveaux objets vides.

Si vous souhaitez 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 remplir le profil initialisé et le sauvegarder, et il sera accessible sur les demandes futures par nom, donc le code de Joel fonctionnera. Je suis en utilisant HttpContext.Current.Profile à l'interne, quand j'ai besoin de créer/accéder au profil immédiatement après la création. Sur toutes les autres demandes, j'utilise ProfileBase.Create(userName), et j'ai exposé une version publique.

notez que Franci a raison: Si vous êtes prêt à créer L'Utilisateur (et les rôles) et le Définir comme authentifié lors du premier voyage aller-retour, et demander à l'utilisateur de se connecter ensuite, vous serez en mesure d'accéder au profil beaucoup plus simplement via le code de Joel sur la demande suivante. Ce qui m'a surpris, c'est que les rôles sont immédiatement accessibles dès la création de l'utilisateur sans aucune initialisation, mais le profil ne l'est pas.

Mon nouveau AccountProfile code:

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

création d'un nouvel utilisateur:

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

Ultérieure accès:

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

remerciements à Franci pour avoir expliqué le cycle de vie de L'authentification - J'appelle FormsAuthentication.SetAuthCookie dans ma fonction de validation, mais je renvoie un bool pour indiquer le succès, car User.Identité.IsAuthenticated ne sera pas vrai jusqu'à la requête suivante.

révisé: je suis un idiot. L'explication ci-dessus fonctionne dans le cas étroit, mais ne résout pas le problème de base: appeler CurrentUser renvoie un nouveau instance de l'objet à chaque fois, si c'est un Profil existant ou pas. Parce que c'est défini comme une propriété, je n'y pensais pas, et j'ai é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();

c'est de ma faute si J'ai complètement négligé ce point fondamental, mais je pense que déclarer CurrentUser comme propriété implique que c'est un objet qui peut être manipulé. Au lieu de cela, il devrait être déclaré comme GetCurrentUser().

17
demandé sur Community 2010-03-30 21:38:16

3 réponses

Création d'un utilisateur ajoute à la liste des utilisateurs. Toutefois, cela n'authentifie ni n'autorise le nouvel utilisateur pour la requête actuelle. Vous devez également authentifier l'utilisateur dans le contexte de la requête courante ou pour les requêtes subséquentes.

Membership.ValidateUser ne validera que les justificatifs d'identité, mais n'authentifiera pas l'utilisateur pour les requêtes actuelles ou futures. FormsAuthentication.SetAuthCookie va définir le ticket d'authentification dans le flux de réponse, donc la prochaine requête sera authentifiée, mais il n'affecte pas l'état de la demande actuelle.

le moyen Le plus facile pour authentifier l'utilisateur serait d'appeler FormsAuthentication.RedirectFromLoginPage (en supposant que vous utilisez l'authentification de formulaires dans votre application). Cependant, celui-ci provoquerait en fait une nouvelle requête HTTP, qui authentifiera l'utilisateur.

alternativement, si vous avez besoin de continuer votre logique pour traiter la requête courante, mais que vous voulez que l'utilisateur soit authentifié, vous pouvez créer un GenericPrincipal, de lui attribuer l'identité du nouvel utilisateur et définissez HttpContext.User à ce principal.

7
répondu Franci Penov 2010-03-30 18:01:02

Vous allez rencontrer des problèmes avec cette approche si vous activez anonymousIdentification. Plutôt que l'Adhésion.GetUser ().Nom d'utilisateur, je suggère D'utiliser HttpContext.Profil.utilisateur.

Comme ceci...

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

pointe du chapeau:SqlProfileProvider - pouvez-vous utiliser le Profil.GetProfile () dans un projet?

1
répondu Bill Mild 2017-05-23 12:16:45

tout d'abord, merci @Jeremy d'avoir partagé vos résultats. Tu m'as aidé à aller dans la bonne direction. Deuxièmement, désolé d'avoir heurté ce vieux poteau. Espérons que cela aidera quelqu'un à relier les points.

la façon dont j'ai finalement obtenu ce travail était d'utiliser la méthode statique suivante à l'intérieur de 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();
}
0
répondu Vinney Kelly 2011-07-01 22:20:11