2

I am not sure I am asking the right question here.

I have a shared page (master page) that calls a couple of partial pages for side menu, header, footer etc.. and all my controllers inherit a BaseController.

Now, depending on the user login status, I need to show different data in all those partial pages and I thought where is the best place to check whether a user is logged in or not - BaseController.

And therein lies my problem. I need to contact one of my web services to see if a user is logged in and get some relevant data if he is. I only need to do this once, and since all controllers inherit from BaseController, each of those partial page calls results in the web service call.

Obviously, I cannot just stick a private bool variable isUserAuthenticated and check for flag, as, each controller will have a new instance of the base controller.

In traditional asp.net projects, I would put this stuff in HttpContext.Current.Items[] and use re-use it but I cannot (somehow) access that in MVC.

I cannot just not inherit from basepage on partial pages as they can also be called independently and I need to know the user login status then too.

What is the best way to call a function just once, or, rather, store a bool value for the duration of one call only? - accessible between controlers..

How do people do this? thanks, sorry, I'm a newbie to mvc!

LocustHorde
  • 6,361
  • 16
  • 65
  • 94
  • A few options for this, but the best is probably found as [Brandon Linton's answer to this question][1] IMO. [1]: http://stackoverflow.com/questions/5453327/how-to-set-viewbag-properties-for-all-views-without-using-a-base-class-for-contro – Timbo Oct 04 '11 at 15:59

2 Answers2

3

You can still use HttpContext.Items, but you'll need to access it via a HttpContextBase instance.

For backwards compatibility you can wrap an HttpContext in an HttpContextWrapper, like so

var context = new HttpContextWrapper(HttpContext.Current);

@iamserious's answer above suggests using a static property - which I strongly disagree with. Setting a static variable is application wide and would mean each and every user would be using the same variable - so all would have the same login data. You want to store it either per user in Session or per Request via HttpContext.Items.


I'd suggest doing something using like this approach, then no matter where you call ContextStash.GetInstance, you'll receive the same instance for the lifetime of the same request. You could also follow the same pattern and use HttpContext.Session instead of HttpContext.Items:

// could use this.HttpContext inside a controller, 
// or this.Context inside a view, 
// or simply HttpContext.Current
var stash = ContextStash.GetInstance(this.HttpContext);

if(!stash.IsSomething)
{
    // do something to populate stash.IsSomething
}

// class
public class ContextStash
{
    const string cacheKey = "ContextStash";

    public ContextStash(HttpContextBase context)
    {
        // do something with context
    }

    // your shared properties
    public bool IsSomething { get; set; }
    public string Foo { get; set; }
    public int Bar { get; set; }

    // instance methods
    public static ContextStash GetInstance()
    {
        return GetInstance(new HttpContextWrapper(HttpContext.Current));
    }

    public static ContextStash GetInstance(HttpContext context)
    {
        return GetInstance(new HttpContextWrapper( context ));
    }

    public static ContextStash GetInstance(HttpContextBase context)
    {
        ContextStash instance = context.Items[cacheKey] as ContextStash;
        if(null == instance)
        {
            context.Items[cacheKey] = instance = new ContextStash(context);
        }
        return instance;
    }
}
Community
  • 1
  • 1
Dave Transom
  • 4,085
  • 3
  • 21
  • 22
  • oh yes! This also explains a bug that I've been having. thanks so much! it is ridiculous that I missed it. I have updated my code with your changes and i think it works well now. again, thank you very much – LocustHorde Mar 22 '12 at 15:43
0

well, if you just want to one variable across several instances of BaseController, use the static keyword, like so:

public class BaseController : Controller
{
    private static bool isUserAuthenticated;
}

Now, no matter how many instances of BaseController you have, they all will share a single isUserAuthenticated variable, you change value in one, you change it in all.

This is the very basic of most object oriented programming and you should really take some time out to go through the concepts of OOP, if you don't mind me saying.

iamserious
  • 5,385
  • 12
  • 41
  • 60