Подтвердить что ты не робот

HttpContext.Items с ASP.NET MVC

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

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

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

Это сводится к тому, что типы 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.Items не передаются" ИЛИ он переносит этот материал, и все в порядке использовать HttpContext.Items.

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

4b9b3361

Ответ 1

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

  • Можно ли использовать Context.Items для кэширования на основе запроса? Да. Если в процессе, для каждого запроса на машину в веб-ферме есть ваши критерии, то Context.Items дает вам это.

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

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

Ответ 2

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

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

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

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

<%=ViewData["Test"] %>

Ответ 3

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