Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load the profile of a newly-logged-in user before the redirect

I started an ASP.NET MVC 2 project and I am building off of the code that was generated automatically.

The problem that I am experiencing is that after a user is logged in, it appears that the profile of the newly-logged-in user is not loaded into the HttpContext, so I get a ProviderException with the message "This property cannot be set for anonymous users" when attempting to set a property value in the current user's profile.

For the POST-only LogOn action, Visual Web Developer 2010 Express basically generated:

    [HttpPost]
    public ActionResult LogOn(LogOnModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            if (MembershipService.ValidateUser(model.UserName, model.Password))
            {
                FormsService.SignIn(model.UserName, model.RememberMe);
        //...

where FormsService is a property of the controller of type FormsAuthenticationService (also generated):

public class FormsAuthenticationService : IFormsAuthenticationService
{
    public void SignIn(string userName, bool createPersistentCookie)
    {
        if (String.IsNullOrEmpty(userName)) throw new ArgumentException("Value cannot be null or empty.", "userName");

        FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
    }

    public void SignOut()
    {
        FormsAuthentication.SignOut();
    }
}

After the FormsService.SignIn(model.UserName, model.RememberMe) line I was assuming that information for the newly-logged-in account would be immediately available to the controller, but this does not appear to be the case. If, for example, I add profile.SetPropertyValue("MyProfileProperty", "test") below the call to FormsService#SignIn, then I get the ProviderException "This property cannot be set for anonymous users".

How do I load the newly-logged-in user's profile into the HttpContext so that I can set a property value in his or her profile before the next request?

like image 279
Daniel Trebbien Avatar asked Jan 19 '11 15:01

Daniel Trebbien


2 Answers

The naming of the function is counter intuitive, but ProfileBase.Create(username) will load the existing profile for an existing user or create a new profile if none exists.

var profile = ProfileBase.Create(userName);

This will not load the profile into ControllerContext.HttpContext.Profile but at least you can access or alter the user profile.

like image 189
Steven K. Avatar answered Nov 18 '22 08:11

Steven K.


The "raw" Forms authentication built into the MVC template does not automatically load the profile. All it does is validate the user against the Membership tables and set the login cookie. If you want profile data persisted in Session state on login, you'll have to do that explicitly:

[HttpPost]
    public ActionResult LogOn(LogOnModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            if (MembershipService.ValidateUser(model.UserName, model.Password))
            {
                FormsService.SignIn(model.UserName, model.RememberMe);
                LoadProfile(model.UserName);
            }
     }

     private void LoadProfile(string UserName)
     {
          MyModelContext ctx = new MyModelContext(); //EF or LINQ2SQL context
          var user = ctx.Users.Where(u => u.UserName == UserName).FirstOrDefault();
          Session.Add("CurrentUser", user);
     }

UPDATE:

I misunderstood the original question. You have to create and save a profile of type ProfileCommon for anonymous users. See this post:

http://forums.asp.net/p/1150958/2619264.aspx

like image 1
Dave Swersky Avatar answered Nov 18 '22 09:11

Dave Swersky