Сохранять данные между разными контроллерами с базовой страницы

Я не уверен, что задаю здесь правильный вопрос.

У меня есть общая страница (главная страница), которая вызывает пару частичных страниц для бокового меню, заголовка, нижнего колонтитула и т. д., и все мои контроллеры наследуют BaseController.

Теперь, в зависимости от статуса входа пользователя, мне нужно показать разные данные на всех этих неполных страницах, и я подумал, где лучше всего проверить, вошел ли пользователь в систему или нет - BaseController.

И в этом моя проблема. Мне нужно связаться с одним из моих веб-сервисов, чтобы узнать, вошел ли пользователь в систему, и получить соответствующие данные, если это так. Мне нужно сделать это только один раз, и поскольку все контроллеры наследуются от BaseController, каждый из этих частичных вызовов страниц приводит к вызову веб-службы.

Очевидно, что я не могу просто вставить приватную логическую переменную isUserAuthenticated и проверить наличие флага, так как каждый контроллер будет иметь новый экземпляр базового контроллера.

В традиционных проектах asp.net я бы поместил этот материал в HttpContext.Current.Items[] и использовал его повторно, но я не могу (каким-то образом) получить к нему доступ в MVC.

Я не могу просто не наследоваться от базовой страницы на частичных страницах, поскольку они также могут вызываться независимо, и тогда мне также нужно знать статус входа пользователя.

Каков наилучший способ вызвать функцию только один раз или, скорее, сохранить логическое значение только на время одного вызова? - доступный между контроллерами..

Как люди это делают? спасибо, извините, я новичок в mvc!


person LocustHorde    schedule 04.10.2011    source источник
comment
Для этого есть несколько вариантов, но лучший, вероятно, можно найти как [ответ Брэндона Линтона на этот вопрос] [1] IMO. [1]: stackoverflow.com/questions/5453327/   -  person Timbo    schedule 04.10.2011


Ответы (2)


Вы по-прежнему можете использовать HttpContext.Items, но вам потребуется доступ к нему через экземпляр HttpContextBase.

Для обратной совместимости вы можете обернуть HttpContext в HttpContextWrapper, вот так

var context = new HttpContextWrapper(HttpContext.Current);

@iamserious ответ выше предлагает использовать статическое свойство, с которым я категорически не согласен. Установка статической переменной распространяется на все приложение и будет означать, что каждый пользователь будет использовать одну и ту же переменную, поэтому у всех будут одни и те же данные для входа. Вы хотите сохранить его либо для каждого пользователя в Session, либо для Request через HttpContext.Items.


Я бы предложил сделать что-то, используя подобный подход, тогда независимо от того, где вы вызываете ContextStash.GetInstance, вы получите один и тот же экземпляр на время существования одного и того же запроса. Вы также можете следовать тому же шаблону и использовать HttpContext.Session вместо 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;
    }
}
person Dave Transom    schedule 20.03.2012
comment
о, да! Это также объясняет ошибку, которая у меня была. Спасибо! смешно, что я пропустил это. Я обновил свой код с вашими изменениями, и я думаю, что теперь он работает хорошо. еще раз большое спасибо - person LocustHorde; 22.03.2012

хорошо, если вы просто хотите использовать одну переменную в нескольких экземплярах BaseController, используйте static, например:

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

Теперь, независимо от того, сколько экземпляров BaseController у вас есть, все они будут совместно использовать одну переменную isUserAuthenticated, вы меняете значение в одном, вы меняете его во всех.

Это самая основа большинства объектно-ориентированных программ, и вам действительно нужно уделить некоторое время изучению концепций ООП, если вы не возражаете, если я скажу.

person iamserious    schedule 04.10.2011