HttpContext.Элементы с ASP.NET MVC
-
16-09-2019 - |
Вопрос
Я создаю свой собственный класс 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 - это ответ, который вы ищете.
Хорошо ли это использовать
Context.Items
для кэширования на основе каждого запроса?ДА.Если в процессе, для каждого запроса, для каждой машины в веб-ферме являются вашими критериями, то Context.Items дает вам это.Является
Context.Items
трудно протестировать с помощью?Что касается тестируемости, я бы скрылContext.Items
за каким-то интерфейсом.Таким образом, вы получаете возможности модульного тестирования без необходимости ссылаться наContext.Items
напрямую.В противном случае, о чем вам нужно протестироватьContext.Items
?Что фреймворк будет хранить и извлекать значения?Держите свой код в неведении относительноSystem.Web
и ты будешь счастливым туристом.Будет
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 действительно взрывается при отключенном состоянии сеанса.Мой единственный совет состоял бы в том, чтобы не хранить сам объект во временных данных, а сохранять простые типизированные поля, как было предложено.Поскольку вы не сериализуете деревья объектов, это не должно так сильно влиять на производительность при запуске вне процесса.