Почему мои переменные экземпляра HttpApplication являются нулевыми? - PullRequest
3 голосов
/ 22 ноября 2011

У меня есть приложение MVC3, в которое я добавил пару простых переменных кэша в качестве свойства. Я добавляю свои данные в Application_Start, а затем в контроллере пытаюсь привести HttpContext.ApplicationInstance обратно к моему типу, чтобы получить к нему доступ. Но свойство всегда равно нулю. Вот пример:

РЕДАКТИРОВАНИЕ НА РАБОЧЕМ ПРИМЕРЕ

public interface IMyMvcApp
{
    Hashtable Cache {get;set;}
}


public class MvcApplication: HttpApplication, IMyMvcApp
{

    public Hashtable Cache 
    {
        get { return Context.Cache["MyStuff"] as Hashtable; }
        set { Context.Cache["MyStuff"] = value}
    }

    public void Application_Start()
    {
        Cache = new Hashtable();
        Cache.Add("key", new object());
    }
}

public class AController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext context)
    {
        var myApp = context.HttpContext.ApplicationInstance as IMyMvcApp;

        Assert.IsNotNull(myApp.Cache);
    }
}

Ответы [ 2 ]

5 голосов
/ 22 ноября 2011

Существует несколько экземпляров приложения, созданного платформой.Чтобы убедиться в этом, добавьте пустой конструктор и установите в нем точку останова.Вы увидите, что этот конструктор будет вызван несколько раз, тогда как Application_Start только один раз.

Таким образом, вместо того, чтобы заново изобретать колеса, вы должны использовать объект Cache, который уже встроен в каркас:

protected void Application_Start()
{
    ...
    Context.Cache["key"] = new object();
}

, а затем:

protected override void OnActionExecuting(ActionExecutingContext context)
{
    var value = context.HttpContext.Cache["key"];
}
3 голосов
/ 18 декабря 2013

В дополнение к правильному ответу Дарина, рекомендующему встроенный кеш, заметка о Одиночных в Asp.Net.

MvcApplication НЕ является синглтоном

Вопреки распространенному мнению, MvcApplication НЕ является глобальным синглтоном. Класс создается несколько раз, по одному экземпляру на каждый «конвейер», поэтому счетчик производительности «Количество экземпляров конвейера» сообщает, сколько экземпляров MvcApplication в настоящее время считается живым. Добавьте ctor по умолчанию и докажите это самостоятельно:

public MvcApplication()
{
    Trace.WriteLine(this.GetHashCode());
}

Отладка прерывает линию или просматривает различные хэш-коды в DebugViewer. Чтобы принудительно увеличить количество экземпляров конвейера, создайте метод с Thread.Sleep (5000), Asp.Net запустит новый экземпляр, как только вы сделаете другой http-запрос параллельно.

Решение - Как создать синглтоны в приложениях Asp.Net (MVC или WebForms)

Если ваш класс MvcApplication, однако, имеет метод Application_Start (), то этот метод фактически вызывается только один раз, для всего процесса. Это позволяет добавлять статические поля в MvcApplication и получать к ним доступ.

Затем к этим полям обращается

MvcApplication.MySingleValue
  • очевидно.

HttpApplication странность

Дизайн класса HttpApplication и его событий довольно странный, что, вероятно, имеет свою причину в некоторой слабой обратной совместимости дизайна с очень старыми ASP-страницами на основе COM. Там объект приложения был фактически создан только один раз, что, несомненно, является источником неверного убеждения, связанного с Asp.Net. Пример странности HttpApplication:

protected void Application_Start()
{
}

Обратите внимание, что здесь нет переопределения!

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

...