views:

204

answers:

3

Consider an ASP.NET MVC application that requires a session variable be set. It's used throughout the app. It'll be set by either reading a hashed value on the browser cookie, or after having the user login.

In the WebForms + Master Page model, I'd check the Page_Load() of the master page. Perhaps not the ultimate event, but it was an easy one to find.

How would you check and enforce the existence of a session variable in ASP.NET MVC? Consider that this question might not involve user login details, but some other piece of data (first visit time, perhaps).

Solution Attempts

public void Application_BeginRequest(Object source, EventArgs e)
{
    HttpApplication application = (HttpApplication)source;
    HttpContext context = application.Context;

    context.Session["SomeDateTime"] =  DateTime.Now.ToString();

    // results in Object reference not set to an instance of an object.
    // context.Session is null
} 
+3  A: 

You have a two options.

1.Place logic in base controller's Execute function

Assuming that all your controllers inherit from a base controller, you can place the logic needed in the override of the Execute() function of the base controller.

public class BaseController : Controller
{
    public BaseController()
    {

    }

    protected override void Execute(System.Web.Routing.RequestContext requestContext)
    {
            // check if the user has the value here using the requestContext.HttpContext object
    }
{

2. Use the Global.asax void Application_PreRequestHandlerExecute(Object source, EventArgs e) function

public void Application_PreRequestHandlerExecute(Object source, EventArgs e)
{
    HttpApplication application = (HttpApplication)source;
    HttpContext context = application.Context;

    // use an if statement to make sure the request is not for a static file (js/css/html etc.)
    if(context != null && context.Session != null)
    {
          // use context to work the session
    }
}

Note: The second part works with any ASP.NET application, WebForms or MVC.

As for enforcing that they have a certain session variable, its very open really. You can redirect to a certain page for them to fill out a form or select an option or something. Or maybe just have a default value that is set to a certain session key if it is not found.

EDIT

While playing with this, I noticed a big issue with Application_PreRequestHandlerExecute approach. The event handler is being called for any request done to the server, be it .css/.js/.html files. I'm not sure if this is an issue with the way my workstation is setup, or just how ASP.NET/IIS works, so I would make sure that this isn't being called on all requests when implementing the approach above.

It is for the previous reasons I wrapped the work to be done in the session with an if statement.

Baddie
@Baddie - thanks for the suggestions! Unfortunately the 2nd option results in `object reference not set`. I've updated the question with details. Thanks again!
p.campbell
Updated my answer. You need to use the `Application_PreRequestHandlerExecute` event instead of the `Application_BeginRequest` as the `Session` is not built there. Take a look at my edit.
Baddie
+1  A: 

Not sure I fully understand the question, but I do this by override the OnActionExecuting method of the controller.

In there you do the code to see if the Session Variable exists. If not, create it, if so then use it.

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
  if (filterContext.HttpContext.Session != null)
  {
       //TODO: Get value from session etc.
  }
  base.OnActionExecuting(filterContext);
}
Graham
A: 

Hey,

As another alternative, the ControllerActionInvoker class invokes every action method; it gets assigned to the controller via the controller factory. So you could subclass this action invoker, everytime an action is invoked (by overridding the InvokeAction method) check here for this existence...

Brian