views:

51

answers:

2

Hey all,

I'm trying my hand at creating a session which stores member information which the application can use to reveal certain navigation and allow access to certain pages and member role specific functionality.

I've been able to assign my MemberLoggedIn object to the session in this way:

    //code excerpt start...

    MemberLoggedIn loggedIn = new MemberLoggedIn();

    if (computedHash == member.Hash)
    {
        loggedIn.ID = member.ID;
        loggedIn.Username = member.Username;
        loggedIn.Email = member.Email;
        loggedIn.Superuser = member.Superuser;
        loggedIn.Active = member.Active;

        Session["loggedIn"] = loggedIn;
    }
    else if (ModelState.IsValid) {
        ModelState.AddModelError("Password", "Incorrect Username or Password."); 
    }

    return View();

That works great. I then can send the properties of Session["loggedIn"] to the View in this way:

    [ChildActionOnly]
    public ActionResult Login()
    {
        if (Session["loggedIn"] != null)
            ViewData.Model = Session["loggedIn"];
        else
            ViewData.Model = null;
        return PartialView();
    }

In the Partial View I can reference the session data by using Model.Username or Model.Superuser.

However, it doesn't seem to work that way in the controller or in a custom Action Filter. Is there a way to get the equivalent of Session["loggedIn"].Username?

+2  A: 

Like this:

MemberLoggedIn user = (MemberLoggedIn)HttpContext.Session["loggedIn"];
SLaks
yikes, `HttpContext.Current`. How about unit testing this? It so much kills the whole ASP.NET MVC thing.
Darin Dimitrov
No! Don't use HttpContext.Current, that's one of the whole reasons MVC abstracted the ASP.Net contexts. http://www.hanselman.com/blog/IPrincipalUserModelBinderInASPNETMVCForEasierTesting.aspx
womp
This seems like its exactly what I'm looking for. I used it without the '.Current' and it worked exactly as I expected.
quakkels
quakkels
@quakkels - that's because there is an instance property of your Controller that is named HttpContext, which is what you're acessing. The example here is using the static singleton System.Web.HttpContext.Current.
womp
Yes, you're right; I edited my answer. As you pointed out, action filters should use `filterContext.HttpContext`.
SLaks
This works well. I think this versus the other answer is probably just a matter of style.
quakkels
+5  A: 

Remember that ASP.Net MVC uses wrappers around the static ASP.Net singletons like Application and Session. This is to allow code to be decoupled from, and unit tested outside of the ASP.Net pipeline.

From an action filter, use:

((MembershipUser)filterContext.HttpContext.Session["loggedIn"]).Username 

And from inside a controller, use:

((MembershipUser)ControllerContext.HttpContext.Session["loggedIn"]).Username
womp
+1, good suggestion about using wrappers.
Darin Dimitrov
I didn't know about ControllerContext. That's cool. I'm more looking for how to get something like ControllerContext.HttpContext.Session["loggedIn"].Username to return the Username (a string) of the logged in member.
quakkels
((MembershipUser)ControllerContext.HttpContext.Session["loggedIn"]).Username. Careful that it's not null before you try accessing the username though.
womp
The part that @quakkels is missing is that he needs to cast the result from `object` to `MemberLoggedIn`. You might want to edit that into your answer and then it will be even better.
Erv Walter
@Erv - thanks, done.
womp
(MemberLoggedIn)filterContext.HttpContext.Session["loggedIn"].Username does not work in my Action Filter
quakkels
((MemberLoggedIn)filterContext.HttpContext.Session["loggedIn"]).Username; also is erroring.
quakkels
What's your action filter method signature? There should be a parameter passed into OnActionExecuting or OnActionExecuted - the "filterContext" is the name of that variable.
womp
oh wait... my bad... this works: `string u = ((MemberLoggedIn)filterContext.HttpContext.Session["loggedIn"]).Username;`
quakkels