Вопрос

Я создаю свой собственный класс ApplicationContext, который использует шаблон singleton.Я хочу сохранить свой экземпляр этого в HttpContext.Items, поскольку он доступен во всех частях запроса.Я читал об использовании HttpContext с ASP.NET MVC, и одна из основных проблем заключается в том, что это усложняет тестирование.Я пытался провести исследование тестируемости HttpContext.Items, но все, что я могу найти, - это данные о сеансе.Одна из немногих вещей, которые я нашел, - это пример главы в профессиональной книге по Wrox ASP.NET 3.5 MVC (ссылка в формате pdf здесь).На странице 15 написано следующее:

Что-то, чем Ты не можешь Воспользоваться:HttpContext.Товары
Выше, в этом разделе, мы признались вам во всем и сказали, что солгали вам:HttpContext не является общим для ASP.NET MVC и ASP.NET Веб-форм.В результате этого вы не можете использовать коллекцию HttpContext.Items для хранения и извлечения битов данных.

Причина этого в том, что после перенаправления на контроллер ваш HttpHandler становится System.Web.Mvc.MvcHandler, который создается с помощью HttpContextWrapper, который будет иметь свое собственное определение HttpContext.Current .К сожалению, во время этого рукопожатия такие вещи, как HttpContext.Элементы не передаются.

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

Теперь я попытался протестировать это, и, насколько я могу судить, если вы перенаправляете на другой контроллер с помощью RedirectToAction , HttpContext.Items остается.Я использую проект по умолчанию ASP.NET MVC, чтобы протестировать это.Что я сделал, так это добавил этот метод в Global.asax.cs:

protected void Application_BeginRequest()
{
    Context.Items["Test"] = "Hello World";
}

И в HomeController.cs я изменил метод Index на:

public ActionResult Index()
{
    return RedirectToAction("About");
}

И изменил метод About на:

public ActionResult About()
{
    Response.Write(Convert.ToString(HttpContext.Items["Test"]));
    return View();
}

Когда я запускаю приложение, страница правильно перенаправляется на /Home/About и Response.Записывает правильную строку "Hello World", установленную в global.asax.cs.

Итак, мне кажется, что я либо не понимаю, что означает книга, когда они говорят "такие вещи, как HttpContext.Элементы не передаются" ИЛИ он действительно передает этот материал, и это нормально - использовать HttpContext.Товары.

Если вы, ребята, рекомендуете мне избегать HttpContext.Items, есть ли другой альтернативный способ сохранения объекта в запросе для каждого запроса?

Это было полезно?

Решение

Ваш вопрос задает несколько вопросов, но я думаю, что пункт № 1 - это ответ, который вы ищете.

  1. Хорошо ли это использовать Context.Items для кэширования на основе каждого запроса?ДА.Если в процессе, для каждого запроса, для каждой машины в веб-ферме являются вашими критериями, то Context.Items дает вам это.

  2. Является Context.Items трудно протестировать с помощью?Что касается тестируемости, я бы скрыл Context.Items за каким-то интерфейсом.Таким образом, вы получаете возможности модульного тестирования без необходимости ссылаться на Context.Items напрямую.В противном случае, о чем вам нужно протестировать Context.Items?Что фреймворк будет хранить и извлекать значения?Держите свой код в неведении относительно System.Web и ты будешь счастливым туристом.

  3. Будет Context.Items выжить RedirectToAction?Нет.Ваш тест недействителен.Он устанавливает "Hello, world" для каждого веб-запроса, и ваш тест охватывает два веб-запроса.Первый - это когда вызывается индексное действие.Второй - это когда RedirectToAction вызывается действие (это HTTP 302).Чтобы это не сработало, установите новое значение в действии Index и посмотрите, сохранено ли оно в действии About.

Другие советы

Используйте словарь TempData, он в основном предназначен для хранения объектов между перенаправлениями действий:

public ActionResult Index()
{
    TempData.Add("Test", "Hello world");
    return RedirectToAction("About");
}

public ActionResult About()
{
    ViewData["Test"] = TempData["Test"];
    return View();
}

Затем извлеките значение в вашем представлении:

<%=ViewData["Test"] %>

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top