2

I am developing an ASP.Net application (intranet) which requires users to authenticate in order to access the portal.

Currently, I save the Employee object into InProc Session State once authenticated successfully. Then on the PageLoad method of the Master Page I check if the Employee's Session is empty (null) which means that the current request was not authenticated, then I redirected to the Login page.

Master Page PageLoad:

if (Session["Employee"] == null) Response.Redirect("~/Login.aspx");

I also use the Employee's Session almost in every page to get some details about the logged in Employee or his level of authority etc ..

My question:

  1. Is the above technique is good to handle such scenario?
  2. Sometimes the Session state is recycled at server (lost), so if I called the Session state in the PageLoad of any chlid page while the Session is null, it will throw an exception because the Master Page onLoad method that checks for the session existence runs only after the child page onLoad method. How and where can I check for the session existence in unified place? Because I don't want to check for the Session existence every time I access the Session state.
  3. Is it possible to trigger a method once a session ends? I tried Session_End in Global.asax but it does not allow me to call any methods or redirect to a page.

Thank you,

Pankaj
  • 9,749
  • 32
  • 139
  • 283
Osama Mortada
  • 171
  • 3
  • 12

2 Answers2

3
  • Is the above technique is good to handle such scenario?

"Good" is subjective, of course. But this scenario should be fine. There are multiple ways to handle user tracking, and I'm curious if anybody has any concrete suggestions.

  • How and where can I check for the session existence in unified place?

What I would recommend is abstracting the Session part of the user tracking into a common object in the application. Within that object you would check if the Session is null, check if the user is logged in, respond accordingly, etc. Then all of the pages (child and master) should just use that object.

This presents a couple of benefits:

  1. You only have to write the Session logic in one place. So you're not constantly writing conditionals on the Session all over the application. The rest of the application just calls methods on a common object.
  2. If you later want to move your user tracking from Session to something else (a database, for example... I've used things like RavenDB and MongoDB to track transient web application data in the past with good results), you only have to change one class. The rest of the application still continues to just use that common object.

For example, the class could have something like this:

public static string GetCurrentUsername()
{
    if (Session["Employee"] == null)
        throw new SomeKindOfAuthenticationException();
    return ((EmployeeObject)Session["Employee"]).Username;
}

Then throughout your application you'd just call the user tracking object to GetCurrentUsername. And in Application_Error you'd handle your authentication exceptions by redirecting to a login page. (This is generally considered to be better practice than, say, returning an empty string in the method above for unauthenticated users. An empty string would have to be checked for constantly throughout the application, whereas the exception handling can happen in a single place. If you need a specific page to not redirect to the login page in this case but rather just not display something, wrap the call in exception handling local to that page and handle it accordingly.)

Consider, of course, that this is mainly a high-level design conjecture and I'm not referring to an actual implementation in front of me. Maybe being static will cause problems with Session? Maybe you need to pass it the Session? Where should you store this class? What other error checking should you do? And so on.

  • Is it possible to trigger a method once a session ends?

Not reliably, in my experience. Consider all of the ways in which a Session could end. A user could click a "logout" link which has logic to clear a Session, or they could just abandon the browser, or their connection could fail for an extended period of time, etc. Web applications are passive request/response systems. Responding to a session timeout without user interaction is tantamount to an active ongoing server-side process, which web applications aren't suited to do.

This is actually one of the reasons why I've experimented with storing this transient data in a database. That way I could have a separate process (such as a Windows Service... something that is designed to run constantly in the background without user requests) monitoring that database and responding to things accordingly. One of the things that can be done in such a setup is a kind of manual Session_End. A separate process would poll the database for Sessions which haven't seen activity in X minutes (by checking a time stamp on an activity tracking record, for example) and respond by clearing the relevant data and performing any other tasks.

In my opinion this fairly cleanly separates the responsibilities of the web application (responding to user requests) and the state tracking (maintaining server-side data).

David
  • 208,112
  • 36
  • 198
  • 279
  • Thanks David for your detailed answer, I have changed my code accordingly, I made a static class like your sample code, but which exception shall I throw? Currently I used ApplicationException with a certain message "Session Not Found", then in the Application_Error method I check if the inner exception's message is equal to that message in order to respond accordingly. And please note that the Employee class is in a separate project not in the App_Code, I do not know if this should make any difference when handling the exception. – Osama Mortada Mar 25 '12 at 23:22
  • @OsamaMortada: You could throw an `ApplicationException`, sure. Maybe a `SecurityException`? In this case you may even want to create a custom exception and throw that. Something like a `NotLoggedInException`. The great thing about a custom exception is that you can define your own fields for it as well. So in `Application_Error` where you check for that exception type, you can easily get data from those custom fields. – David Mar 26 '12 at 00:51
  • Thanks David, I think the SecurityException is better because I noticed that the ApplicationException is always thrown within the HttpException and I had to get it from the inner exception!! I do not know why the Application Exception is always warped within an HttpException? I will try also the custom exceptions, Thanks David:) – Osama Mortada Mar 26 '12 at 08:41
  • While for example membership provider or WIF is used for authentication, the authenticated user is stored by the framework in current thread context and can be retrieved from `System.Threading.Thread.CurrentPrincipal` or, in web application, also from `System.Web.HttpContext.Current.User`. – jwaliszko Nov 19 '12 at 10:30
0

Is the above technique is good to handle such scenario?

No

How and where can I check for the session existence in unified place?

You could add the session related logic into a Base Page this discussion would be helpful for you ASP.net "BasePage" class ideas


You can inherit the BasePage in your all aspx pages. Below is the Sample Example

public class BaseClass : System.Web.UI.Page
{
    public String UserName
    {
        get
        {
            if (HttpContext.Current.Session["UserName"] == null)
                Response.Redirect("Login.aspx");
            return Convert.ToString(HttpContext.Current.Session["UserName"]);
        }
    }

I also use the Employee's Session almost in every page to get some details about the logged in Employee or his level of authority etc ..

    public String FirstName
    {
       get
       {
           if (UserName == null)
              return String.Empty;
           return Convert.ToString(HttpContext.Current.Session["FirstName"]);
       }
    }
}

Community
  • 1
  • 1
Vibes
  • 33
  • 6