web app advice

Posts   
 
    
erichar11
User
Posts: 268
Joined: 08-Dec-2003
# Posted on: 28-Oct-2004 12:35:56   

Not sure if this is the appropriate forum, so please feel free to move.

I have a problem with a web based application. In the global.ascx application_beginRequest event I have an object called UserSettingsManager which grabs the user settings on each request. The problem is that the application_beginRequest event does not have access to session data. Consequently, I store the userId and companyId in the session object when the user logs in. So when a aspx page is called I want to update the UserSettingsManager object to include and filter the data based on the userId and companyId contained within the session object. So I created a method called SetSessionData (SetSessionData(int companyId, int userId) on the userSettingsManager object which should update the userId and companyId properties for the UserSettingsManager. This works, however, any object I call uses the UserSettingsManager data prior to the the SetSessionData rather than using the data after calling the SetSessionData method. I'm not sure what is the appropriate way to handle this. Was looking for any insight as I'm sure this must be a common problem. Here is example code:

public class MyClass { public static void Main() { Test t = new Test(2,3); t.OutputBefore(); t.SetSessionData(3, 4); t.OutputAfter(); Console.ReadLine(); } }

public class Test { public int appId = -1; public int pageId = -1; private int userId = -1; private int companyId = -1;

public int UserId
{
    get{return this.userId;}
    set{this.userId = value;}
}

public int CompanyId
{
    get{return this.companyId;}
    set{this.companyId = value;}
}

public Test(int appId, int pageId)
{
    this.appId = appId;
    this.pageId = pageId;
    AppManager app = new AppManager(this.userId);
    app.Output();
}

public void OutputBefore()
{
    Console.WriteLine("");
    Console.WriteLine("Output Before SetData");
    Console.WriteLine("value of appId: " + this.appId);
    Console.WriteLine("value of pageId: " + this.pageId);
    Console.WriteLine("value of companyId: " + this.companyId);
    Console.WriteLine("value of userId: " + this.userId);
}

    public void OutputAfter()
{
    Console.WriteLine("");
    Console.WriteLine("Output After SetData");
    Console.WriteLine("value of appId: " + this.appId);
    Console.WriteLine("value of pageId: " + this.pageId);
    Console.WriteLine("value of companyId: " + this.companyId);
    Console.WriteLine("value of userId: " + this.userId);
}


public void SetSessionData(int companyId, int userId)
{
    this.companyId = companyId;
    this.userId = userId;       
}

}

// This is where the problem occurs, AppManager uses the initial data rather than the data after SetData is called public class AppManager { private int userId; public int UserId { get{return this.userId;} set{this.userId = value;} }

public AppManager(int userId)
{
    this.userId = userId;
}

public void Output()
{
    Console.WriteLine("AppManager userId: " + this.userId + " AppManager userId should be 4 not -1");
}

}

If anyone can offer a better solution or suggestion, it would be greatly appreciated.

Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 28-Oct-2004 22:35:25   

I just ran across this issue myself. Apparently, what I found was that only objects related to a PAGE or CONTROL have access to the current session.

In the page_init or page_load, I have code like this:

securityInfo = (SecurityInfo)Session["SecurityInfo"]; if (securityInfo == null) { securityInfo = MyFacade.GetSecurityInfo(Context.User.Identity.Name) Session["SecurityInfo"] = securityInfo; }

This might seem like a PITA, but you could always create a page that derives from page, and put this code into your derived page. Then derive all new pages from your derived page. You could also substitute userControl for page in this scenario, if all of your pages were really user controls instead of pages..

One other thing, is what about the Cookies Collection? If Application_OnBeginRequest had access to the current users cookies, you might be able to tackle it from that approach.

erichar11
User
Posts: 268
Joined: 08-Dec-2003
# Posted on: 29-Oct-2004 00:26:06   

Thanks devildog, I think I'm going to try and tackle it from the cookies approach. Thanks for the help.

uydo
User
Posts: 43
Joined: 09-Dec-2003
# Posted on: 29-Oct-2004 17:04:08   

This might seem like a PITA, but you could always create a page that derives from page, and put this code into your derived page. Then derive all new pages from your derived page. You could also substitute userControl for page in this scenario, if all of your pages were really user controls instead of pages..

With that assumption, then if we need a LoginID property, we have to define it twice, one in the master page, and one in master-usercontrol with the same code? Is there any idea about this?

Uy.

Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 29-Oct-2004 17:53:35   

uydo wrote:

With that assumption, then if we need a LoginID property, we have to define it twice

It is feasable that the page would need access to the LoginId and all user controls would needs access to the LoginId.

You would only need to define LoginId in one place, IMO. Assume that you had an interface called IUserInfo, and this interface defined a property LoginId. Also assume that you have a class called UserInfo, that implements the interface.

When the user attempts to login, if their credentials are valid, create an instance of UserInfo and stick it somewhere. In the user controls, create a property of type UserInfo. When the master page initializes it's controls, pass the UserInfo to the user controls that are being created. Now the user control should know about the UserInfo object.

Once this is in place, you should be able to access the UserInfo object like this:

MyPage.UserInfo.LoginId

OR

MyControl.UserInfo.LoginId

The reason that I chose to use an interface is because we could actually create another interface, that is implemented by the page and the user control, that contain IUserInfo as an argument for a method that sets the internal value of userInfo for the given page or control. Once this is done, you have a standard way to set a page's UserInfo property.

erichar11
User
Posts: 268
Joined: 08-Dec-2003
# Posted on: 29-Oct-2004 18:39:05   

Thanks to devildog, I implemented this via cookies (didn't want to but its pretty clean so I can live with it) Basically, what I do, when a user logs in a cookie is created with the loginId and companyId. Then in the global.ascx Application_beginRequest event, I read the cookie and grab the loginId and companyId which is then passed into my UserSettingsManager object (this object has all the user settings for a given user).

public Application_beginRequest() { HttpCookie cookie = Request.Cookies["CookieData"]; int loginId = int.Parse(cookie["loginId"]); int companyId = int.Parse(cookie["companyId"]);

 HttpContext.Items.Add("UserSettings", new UserSettingManager(loginId, companyId));

}

This approach seems to work pretty well so far. Since the UserSettingsManager is now part of the context it's accessable from every page/control, so if I want to get the login user on a given page I do this.

public SomePage_Load() { UserSettingsManager usm = (UserSettingsManager)HttpContext.Current.Items["UserSettings"]; int loginUser = usm.LoginUser; }

So now I have all the info I need regarding userSettings in one object that is easily accessible. Please note, this is a web app.