Как вы сохраняете значение глобальных переменных между различными вызовами методов действий в MVC3?
Я разрабатываю веб-приложение ASP.NET MVC 3 с помощью Razor и С#.
Я только что обнаружил, что у меня есть некоторые проблемы с глобальными переменными, возможно потому, что я относительно новичок в MVC.
У меня есть контроллер с некоторыми глобальными переменными и методами действий. Я объявил глобальную переменную, чтобы позволить действительным методам манипулировать ею и отражать манипуляции ко всем методам действий. У меня есть следующая ситуация:
public class myController : Controller
{
private string _MyGlobalVariable;
public ActionResult Index()
{
_MyGlobalVariable = "Hello";
//other code
return View("MyView");
}
public ActionResult Print()
{
_MyGlobalVariable += "Print";
return View("PrintView", _MyGlobalVariable);
}
}
Метод действия Печать() вызывается с Html.ActionLink() из представления MyView.
Удивительно, что значение _MyGlobalVariable не сохраняется! Таким образом, значение _MyGlobalVariable перед командой _MyGlobalVariable += "Print"
равно нулю.
Я ошибаюсь? Как я могу сохранить значение глобальных переменных между вызовами в Views?
Спасибо
Франческо
PS: в моем конкретном случае глобальная переменная является Dictionary<K,V>
, но, я думаю, она не меняет логику.
PPS: Я знаю, что вы можете использовать ViewModels вместо глобальных переменных для передачи данных между методами действий, но в моем случае гораздо меньше кода, если я использую Dictionary<K,V>
, который обычно не переношу в ViewModels (я использую POCOs или Lists<T>
)
Ответы
Ответ 1
Каждый запрос получает новый экземпляр контроллера.
Поскольку ваша переменная является полем экземпляра, она не сохраняется.
Вы можете исправить это, сделав его static
или используя состояние приложения.
Однако не.
Вы никогда не должны использовать изменяемое глобальное состояние в веб-приложении.
В частности, если вы получите два запроса одновременно, ваше поле будет испорчено.
В зависимости от того, что вы пытаетесь сделать, вы можете использовать состояние сеанса или файлы cookie.
Ответ 2
Прежде всего, в С# нет глобальных переменных. То, что вы ищете, представляет собой статическую переменную, к которой можно получить доступ через сам класс. Поскольку для каждого запроса создается новый экземпляр контроллера, значение вашей переменной теряется.
Вам нужно будет объявить свою переменную как таковую:
private static string _MyGlobalVariable = "insert default value here";
И получить его как таковой:
MyControllerClass._MyGlobalVariable
Кроме того, эта переменная будет доступна только из методов класса myController, так как вы объявили ее приватной.
В дополнение к этому вы, вероятно, захотите заблокировать переменную при ее использовании, так как в конечном итоге вы столкнетесь с условиями гонки.
Примечание: я бы не предложил сделать это таким образом
Ответ 3
Поскольку все говорят, что глобальные переменные здесь не будут работать. Даже если бы они были хорошей идеей, они не работали бы в сценарии веб-фермы, так как значение было бы только на одной машине.
Действие вашего контроллера индекса может выглядеть примерно так.
public ActionResult Index()
{
myModel myStronglyTypedModel = new myModel();
myStronglyTypedModel.SomeStateIWantToKeep = "Hello";
return View(myStronglyTypedModel);
}
Тогда в вашей печати это сделало бы
public ActionResult Print(myModel myStronglyTypedModel)
{
myStronglyTypedModel.SomeStateIWantToKeep += "Print";
return View("PrintView");
}
И ваш взгляд может начинаться с
@ModelType myModel
и поэтому ваше представление будет строго напечатано.
Я парень vb, поэтому кто-то может исправить мой С#. Я подозреваю, что директива @ModelType в vb является @model в С#, но не проверена.
Приветствия
Ответ 4
Вероятно, вы должны использовать ViewData для этого или использовать HttpContext. ViewData будет действителен только для вашего текущего запроса, поэтому, как правило, это лучшая альтернатива, чем прямое использование объекта сеанса, поскольку ваши данные удаляются и недоступны при следующем запросе. Использование объекта сеанса может пострадать от проблем с перекрытием нескольких запросов.
Ответ 5
Вы можете использовать словарь TempData для сохранения одного шага вызова контроллера. TempData отправляет ваши данные только на один следующий сеанс, если вы хотите сохранить свои данные во весь сеанс, вы должны инициализировать этот TempData в каждом контроллере методов, который вы хотите.
public ActionResult Index()
{
if (TempData["MyGlobalVariable"] == null)
return RedirectToAction("MyGlobalVariableInitializer");
else
TempData["MyGlobalVariable"] =(string)TempData["MyGlobalVariable"]+" world";
.
.
.
}
в MyGlobalVariableInitializer, вы впервые инициализируете MyGlobalVariable.
public ActionResult CompanySelection()
{
return View();
}
public ActionResult MyGlobalVariableInitializer()
{
TempData["MyGlobalVariable"] = "Hello";
return RedirectToAction("Index");
}