My understanding of that was that you were looking for a way to interrogate
session objects themselves directly...
Well, I was kind of expecting to do that, however, on realising that
there was no built in property of the session object that did the job,
elected to store the property in the session 'array' (is that what
it's called?)
Presumably, if they don't proceed any further than the login page, nothing
gets added to the collection, even though a session has actually been
created...?
Yep. A little bit to my frustration actually! The original intention
was the capture the session start event and add the session to the
collection then, however, there was a problem that I couldn't get
around where it appeared that the session which was added to the
collection was not the same object as the session which they
eventually logged in under (I'm not sure if that makes much sense). I
note that you've mentinoed below that session IDs are not guaranteed
to be unique. I havevn't clicked that link yet, but, if it's referring
to the regenerateExpiredSessionId property of a session, then I played
around with that as well.
I've just read that link you sent. I'm now wondering if the problem I
was having above was due to this. I can't remember if I was testin
IsNewSession or not.... (it was late in the day and I was tired!!)
Also, bear in mind that SessionID values are not guaranteed to be unique in
every instance:
http://www.google.com/search?q="ASP.NET"+SessionID+unique&rls=com...
Noted.
Luckily you're using inproc sessions...
Indeed
For the record, I had MAJOR headaches with this as well. Ideally, the
end event should've been captured in a HTTPModule. I'm stuffed if I
could get it working though. I found an article (
http://codebetter.com/
blogs/karlseguin/archive/2006/06/12/146356.aspx) that touches on the
issues, (search for "There's a way to hook into those events, but as
far as I know, it's something of a nightmare" in the feedback).
I reckon that this is a bug in the framework. It was 'unnaceptably'
difficult (impossible for me anyway) to catch a reliable end event in
a httpmodule. I had to resort to the 'ugly' global.asax.
Presumably your site has a logout facility which tears down the session
causing Session_End to fire? Obviously, if a user simply closes their
browser (or moves to another site) without explicitly logging out, this
won't fire so at that point it will appear that they are still logged in
even though they are no longer using your site...
Correct. As you'd expect, it 'eventually' fires when the session
timesout and their session is removed. This is exactly the reason why
I wanted to find out how long they'd been inactive. The whole point of
this excercise was to find out how many were using the site at a given
time so that we could 'sneak in' an unscheduled site restart /
upgrade. If someone's logged in, but not accessed a page for 10
minutes, then I'm happy to reset the app and bounce their session.
How do you work out who is logged in i.e. which SessionID relates to which
user...?
Do you store their UserID / SAMAccountName in the collection too...?
When they log in, I create an instance of clsUserSession (below).
This takes their session object as a constructor.
I then add them to a keyedcollection (clsSessionBank) that is stored
in the Application array. They key for this is their sessionID. I can
loop through this and read the Session property to get access to the
Session array. There are also properties on clsUserSession that read
the Session array (LastAccessedTime).
/// <summary>
/// Used to wrap session variables for online user tracking.
/// </summary>
public class clsUserSession
{
private HttpSessionState _session;
private string _ip;
public clsUserSession(HttpSessionState session, string IP)
{
_session = session;
_ip = IP;
}
public DateTime LastAccessedTime
{
get
{
if(_session[eSession.SessionLastAccessedTime.ToString
()]==null)
{
return new DateTime(1, 1, 1);
}
else
{
return ((DateTime)_session
[eSession.SessionLastAccessedTime.ToString()]);
}
}
}
public HttpSessionState Session
{
get
{
return _session;
}
}
.....
}
public class clsSessionBank : KeyedCollection<string, clsUserSession>
{
int _maxSimultaneous = 0;
protected override string GetKeyForItem(clsUserSession item)
{
return item.Session.SessionID;
}
protected override void InsertItem(int index, clsUserSession
item)
{
base.InsertItem(index, item);
_maxSimultaneous = System.Math.Max(_maxSimultaneous,
this.Count);
}
public int MaxSimultaneous
{
get
{
return _maxSimultaneous;
}
}
}
What is the purpose of that...?
Now that you mention it, absolutely none!!
Actually, that's not really true actually. The other day, I had a user
in there that was idle for 10 minutes (which, normally, I'd consider
safe to bounce). However, because I display the page he's on, I could
see that he was filling in a 'feedback form'.... hence, assumed he was
typing. As it turned out, at 13 minutes, he submitted the form, then
logged out. I guess it's a good thing I didn't bounce him!