Как сохранить значение глобальных переменных между различными вызовами методов действий в MVC3?

я разрабатываю 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 вид.

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

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

спасибо

Франческо

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

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

5 ответов


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

вы можете исправить это, сделав его static или с помощью состояния приложения.

однако, не.
Никогда не следует использовать изменяемое глобальное состояние в веб-приложении.

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

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


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

вам нужно будет объявить переменную как таковую:

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

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

MyControllerClass._MyGlobalVariable

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

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

примечание: Я бы не предложил делать это таким образом


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

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

    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#, но не проверена.

Ура


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

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