Question

I have a user reporting that when they use the back button to return to a web page that they come back as a different person. It seems like they may be accessing a different users profile.

Here are the important parts of the code:

//here's the code on the web page

public static WebProfile p = null;

protected void Page_Load(object sender, EventArgs e)
{
    p = ProfileController.GetWebProfile();
    if (!this.IsPostBack)
    {
         PopulateForm();
    }       
}

//here's the code in the "ProfileController" (probably misnamed)
public static WebProfile GetWebProfile()
{
    //get shopperID from cookie
    string mscsShopperID = GetShopperID();
    string userName = new tpw.Shopper(Shopper.Columns.ShopperId,        mscsShopperID).Email;
    p = WebProfile.GetProfile(userName); 
    return p;
}

I'm using static methods and a static WebProfile because I need to use the profile object in a static WebMethod (ajax pageMethod).

  • Could this lead to the profile object being "shared" by different users?
  • Am I not using static methods and objects correctly?

The reason I changed WebProfile object to a static object was because I need to access the profile object within a [WebMethod] (called from javascript on the page).

  • Is there a way to access a profile object within a [WebMethod]?
  • If not, what choices do I have?
Was it helpful?

Solution

A static object is shared across all instances of an application so if you alter the value of a static object, that alteration will be reflected across all instances of the application which access that object. Therefore if your web profile is reassigned by another thread (i.e. a second user visiting a page) inbetween you setting it for the current user, it will contain information different to what you expect.

To get around this your code should look something like:

public WebProfile p = null;

protected void Page_Load(object sender, EventArgs e)
{
    p = ProfileController.GetWebProfile();
    if (!this.IsPostBack)
    {
         PopulateForm();
    }       
}

public static WebProfile GetWebProfile()
{
    //get shopperID from cookie
    string mscsShopperID = GetShopperID();
    string userName = new tpw.Shopper(Shopper.Columns.ShopperId,        mscsShopperID).Email;
    return WebProfile.GetProfile(userName); 
}

Note that the static object has not been set and the returned value should be assigned to a NON STATIC instance of the web profile class in your calling method.

Another option is to LOCK your static variable for the whole time it is in use but this will lead to severe degradation in performance as the lock will block any other requests for the resource until the current locking thread is completed - not a good thing in a web app.

OTHER TIPS

@Geri

If the profile doesn't often change for the user you have the option of storing it in the current Session state. This will introduce some memory overhead but depending on the size of the profile and the number of simultaneous users this could well be a non-issue. You'd do something like:

public WebProfile p = null;
private readonly string Profile_Key = "CurrentUserProfile"; //Store this in a config or suchlike

protected void Page_Load(object sender, EventArgs e)
{
    p = GetProfile();

    if (!this.IsPostBack)
    {
        PopulateForm();
    }       
}

public static WebProfile GetWebProfile() {} // Unchanged

private WebProfile GetProfile()
{
    if (Session[Profile_Key] == null)
    {
        WebProfile wp = ProfileController.GetWebProfile();
        Session.Add(Profile_Key, wp);
    }
    else
        return (WebProfile)Session[Profile_Key];
}

[WebMethod]
public MyWebMethod()
{
    WebProfile wp = GetProfile();
    // Do what you need to do with the profile here
}

So that the profile state is retrieved from session whenever necessary and should get around the need for static variables.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top