Как вы сохраняете значение глобальных переменных между различными вызовами методов действия в MVC3? - PullRequest
15 голосов
/ 09 мая 2011

Я занимаюсь разработкой веб-приложения ASP.NET MVC 3 с использованием Razor и C #.

Я только что обнаружил, что у меня есть некоторые проблемы с глобальными переменными, возможно, потому что я относительно новичок в 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);
    }
}

Метод действия Print () вызывается с Html.ActionLink () из MyView View.

Удивительно, что значение _MyGlobalVariable не сохраняется!Таким образом, значение _MyGlobalVariable перед инструкцией _MyGlobalVariable += "Print" равно нулю.

Я делаю какую-то ошибку?Как сохранить значение глобальных переменных между вызовами в Views?

Спасибо

Francesco

PS: в моем конкретном случае глобальной переменной является Dictionary<K,V>, но ядумаю, это не меняет логику.

PPS: я знаю, что вы можете использовать ViewModels вместо глобальных переменных для передачи данных между методами действия, но в моем случае гораздо меньше кода, если я использую Dictionary<K,V>, который обычно яне переносить в ViewModels (я использую POCOs или Lists<T>)

Ответы [ 5 ]

31 голосов
/ 09 мая 2011

Каждый запрос получает новый экземпляр контроллера.
Поскольку ваша «переменная» является полем экземпляра, она не сохраняется.

Это можно исправить, установив static или используя состояние приложения.

Однако не .
Вы никогда не должны использовать изменяемое глобальное состояние в веб-приложении.

В частности, если вы получите два запроса одновременно, ваше поле будет перепутано.

В зависимости от того, что вы пытаетесь сделать, вы можете использовать состояние сеанса или файлы cookie.

4 голосов
/ 09 мая 2011

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

Вам нужно будет объявить вашу переменную следующим образом:

private static string _MyGlobalVariable = "insert default value here";

И получить к ней доступ как таковой:

MyControllerClass._MyGlobalVariable

Кроме того, эта переменная будет доступна только из методов класса myController, так как она объявлена ​​закрытой.

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

примечание: я бы не советовал делать это таким образом

2 голосов
/ 19 октября 2014

Вы можете использовать словарь 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");
    }
2 голосов
/ 09 мая 2011

Как все говорили, глобальные переменные здесь не будут работать. Даже если бы они были хорошей идеей, они не работали бы в сценарии веб-фермы, поскольку значение было бы только на одном компьютере.

Ваше действие контроллера индекса может выглядеть примерно так ...

    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, поэтому кто-то не стесняется исправить мой c #. Я подозреваю, что директива @ModelType в vb - это @model в c #, но не проверила.

Приветствия

1 голос
/ 09 мая 2011

Вы, вероятно, должны использовать ViewData для этого ИЛИ использовать HttpContext. ViewData будет действительным только для вашего текущего запроса, поэтому, как правило, это лучшая альтернатива, чем прямое использование объекта сеанса, поскольку ваши данные удаляются и недоступны при следующем запросе. При использовании объекта сеанса могут возникнуть проблемы с перекрытием нескольких запросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...