Session Madness

M

Mr Newbie

I have written a Custom Control Menu. Its fairly simple but it works well
enough. In order to simplify things I decided to store the Menu1 custom
control in Session. In the page load event below, it retreives the Menu
from session and assigns its reference to Menu1.

Within the Page_Load event I can see its internal values which have been
retreived for each menu item and so it looks good. However, when the Render
method is called of Menu1, everything seems to have disapeared, there are no
menuitems and the count is zero.

Im sure I am doing something fundamentally stupid, but I cant see it for
staring !

Does anyone have a clue ?

'Check is this is already in Session

If (Session("Menu") Is Nothing) Then

'Build the menu

Menu1.Add(New TONEControls.Menu.MenuItem("MItem", "default.aspx", "Home",
False, True))

Menu1.Add(New TONEControls.Menu.MenuItem("MItem", "CreateExpenses.aspx",
"New Expenses", False, False))

Menu1.Add(New TONEControls.Menu.MenuItem("MItem", "Review.aspx", "Review",
False, False))

'Add it

Session("Menu") = Menu1

Else

'Get it from session

Menu1 = Session("Menu")

End If

Menu1.SetSelected(0)
 
K

Kevin Spencer

How and where is the Menu Control created?

Just as a note, it is generally bad practice to store UI elements in
Session. It is better to store the data they contain in Session.

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
Complex things are made up of
Lots of simple things.
 
M

Mr Newbie

Thanks for your reply Kevin,

OK to answer your questions.

1. How is it created.
The Custom Control, is just that, it resides in a library which is part of
the web solution. The menu is a simple table creation which uses css to set
the background mouseover, mouseout and click events.

The control has an ArrayList collection inside it which stores objects
instantiated from a nested class within the control. These objects are the
menu items themselves containing properties such as href, IsSelected, class
( style sheet class ) etc.

The overriden Render sub takes responsibility for setting up the javascript
for style switching when the mouse events go off.

2.Where
The control is registered as normal as a custom control in the page template
an its ID is Menu1, and is defined in the Codebehind for the Page.

During Page_Load, we detect if the control has been stored in session and if
not, we create the Menu using its Add method and instantiating the MenuItem
anonymously in the constructor. If the Menu has already been stored we
assign its Session("Menu") reference to Menu1. So far so good, we then
select the MenuItem which is currently selected depending on the page it's
on. And this is highlighted as the current position on the site ( Current
Page ).

Everything is fine UNTIL we enter the Render event of the Menu control on
Postback, and although we are in an object, its menuList ( ArrayList
containing the items ) is empty and the count is also empty as if it has
been freshly instantiated.

I'm obviously missing something basic, I hope you will be able to shed some
light on it.

PS: Why is it bad to store the UI objects in Session ( Just interested to
know )

Best Regards

The Inimitable Mr Newbie º¿º
 
C

CsaaGuy

On the line: Menu1 = Session("Menu"), Your not using either Option
Explict or Option Strict. Maybe the the cast is not correct. This might
account for your not getting out of the session object.
 
M

Mr Newbie

I only wish it were that simple.

I can do this no problem during the page load on GET
Session("Menu") = Menu1 '//Store it
Menu1 = Nothing '// Basically zapping the object set in the page class.
Menu1 = Session("Menu") '// Retreive

And this works OK.

On Postback, it still reads the Menu from the Session, but as soon as you
get into Render on the control, then its lost.

Beats the hell outa me !
 
K

Kevin Spencer

Howdy Mr N.,

I kind of suspected that the Control was registered in the Page, and defined
in the CodeBehind. I cannot be sure of this, but I believe this has
something to do with why the Control is not being rendered as expected,
which also brings me to my second point, about which you asked. That is,
that it is not a good idea to store UI elements in Session. So, I'll start
with that.

First, Session exists for every user that is currently using the
application. Whatever users are visiting this particular page, they will
have a copy of the Contro in their Session State. This means that storing
the Control in Session creates a larger footprint (multiplied by the number
of Sessions in which it is stored) than storing only the data. The Control
is a UI element, and therefore contains data and process which does not need
to be stored in memory. Controls are instantiated with each Request, and
pass out of scope when the Page class exits ( matter of milliseconds),
ensuring that they will be Garbage Collected, freeing up server memory
resources. Anything stored in Session remains in state until the Session is
destroyed, which by definition means at least 20 minutes (after the user has
stopped sending Requests for 20 minutes). In other words, a good rule of
thumb is to keep anything that doesn't need to be in Session out of Session.

In addition, this Control is instantiated by the Page class when a Request
is received. Now you have 2 instances of the Control, one more than
necessary, and one which will be discarded in short order, making it
irrelevant. Let's say that you *did* have a reson for storing a Control in
Session (I can't think of one, but for the sake of argument...). There is
therefore no need to have one registred in the page. The Control can be
dynamically added to the Page at run-time.

And that brings me back to the root of your problem. I believe there is a
conflict occurring between the Control registred in the Page, and the
Control stored in Session. It has something to do with (forgive me for not
taking the time to investigate fully) the order in which Controls are
created, stored, and rendered in a Templated Control that contains Child
Controls (the Page). I believe that the Session Control is probably not
being loaded at the right time in the sequence (most probably - remember our
discussion about CreateChildControls?). Somehow, the registred Control is
the one being rendered.

What I would do (and in fact, have done in an app with a very similar type
of menu) is to keep the registered Control in the page, store the ArrayList
in Session, and load the Control from the ArrayList at run-time.

Again, forgive me for not having the time to look extensively into the exact
details. I do love to research, but my wife wants me to spend some time with
her!

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
There's a seeker born every minute.
- Dr. "Happy" Harry Cox
 
M

Mr Newbie

Well Kevin, whatever the truth behind the problem, your suggestion saved the
day. I implemented it from within the Menu object. I'm not sure if I really
needed to prefix the menuList identifier with the ControlID, but I was
erring on the side of duplicate ID's. But in this instance, the ID's are
allways likley to be the same anyway so I dont think it matters.

Public Sub SaveInSession()
If Me.Page.Session(Me.ID & "_" & "menuList") Is Nothing Then
Me.Page.Session(Me.ID & "_" & "menuList") = menuList
End If
End Sub

Public Sub RetreiveFromSession()
menuList = Me.Page.Session(Me.ID & "_" & "menuList")
m_count = menuList.Count
End Sub

And in the Page. . . .

'Check is this is already in Session
If Not Page.IsPostBack Then

'Build the menu
Menu1.Add(New TONEControls.Menu.MenuItem("MItem",
"default.aspx", "Home", False, True))
Menu1.Add(New TONEControls.Menu.MenuItem("MItem",
"CreateExpenses.aspx", "New Expenses", False, False))
Menu1.Add(New TONEControls.Menu.MenuItem("MItem", "Review.aspx",
"Review", False, False))
'Add it
Menu1.SaveInSession()

Else

'Get it from session
Menu1.RetreiveFromSession()

End If

Menu1.SetSelected(0)

As allways thanks for taking the time to reply. The issue regarding process
vs data makes sense even if we have not uncovered the underlying problem.
 
K

Kevin Spencer

My pleasure, as always, Mr. N!
As allways thanks for taking the time to reply. The issue regarding
process vs data makes sense even if we have not uncovered the underlying
problem.

Yes. Unfortunately, there are only so many hours in a day. No doubt, we
will, either separately or together, encounter and solve the remaining
riddles on another day!

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
There's a seeker born every minute.
- Dr. "Happy" Harry Cox
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top