web-dev-qa-db-fra.com

Comment conservez-vous la valeur des variables globales entre les différents appels de méthodes d'action dans MVC3?

Je développe une application Web ASP.NET MVC 3 utilisant Razor et C #.

Je viens de découvrir que j'ai des problèmes avec les variables globales, probablement parce que je suis relativement nouveau sur MVC.

J'ai un contrôleur avec quelques variables globales et méthodes d'action. J'ai déclaré une variable globale afin de permettre aux méthodes d'action de la manipuler et de refléter les manipulations à toutes les méthodes d'action. J'ai la situation suivante:

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);
    }
}

La méthode d'action Print () est appelée avec un Html.ActionLink () de la vue MyView.

La chose surprenante est que la valeur de _MyGlobalVariable n'est pas conservée! Ainsi, la valeur de _ MyGlobalVariable avant l'instruction _MyGlobalVariable += "Print" est égal à null.

Suis-je en train de faire une erreur? Comment puis-je conserver la valeur des variables globales entre les appels aux vues?

Merci

Francesco

PS: dans mon cas spécifique, la variable globale est un Dictionary<K,V> mais je suppose que cela ne change pas la logique.

PPS: Je sais que vous pouvez utiliser ViewModels au lieu de variables globales pour passer des données entre les méthodes d'action, mais dans mon cas, c'est beaucoup moins de code si j'utilise un Dictionary<K,V> que je n'habille généralement pas dans ViewModels (j'utilise POCO ou Lists<T>)

16
CiccioMiami

Chaque demande obtient une nouvelle instance de contrôleur.
Puisque votre "variable" est un champ d'instance, il ne persiste pas.

Vous pouvez résoudre ce problème en le faisant static, ou en utilisant l'état de l'application.

Cependant, ne pas.
Vous ne devez jamais utiliser un état global mutable dans une application Web.

En particulier, si vous recevez deux demandes en même temps, votre champ sera gâché.

Selon ce que vous essayez de faire, vous pouvez utiliser l'état de session ou les cookies.

32
SLaks

Tout d'abord, il n'y a pas de variables globales en C #. Ce que vous recherchez est une variable statique, accessible à travers une classe elle-même. Puisqu'une nouvelle instance de contrôleur est créée à chaque demande, la valeur de votre variable est perdue.

Vous devrez déclarer votre variable comme telle:

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

Et accédez-y comme tel:

MyControllerClass._MyGlobalVariable

De plus, cette variable ne sera accessible qu'à partir des méthodes de la classe myController, car vous l'avez déclarée privée.

En plus de cela, vous voudrez probablement verrouiller la variable à chaque utilisation, car vous finirez par vous retrouver dans des conditions de course.

note: je ne suggérerais pas de le faire de cette façon

4
cwharris

Vous pouvez utiliser TempData Dictionary pour enregistrer un contrôleur d'appel en une étape. TempData envoie vos données à une seule session suivante si vous souhaitez conserver vos données à toutes les sessions, vous devez initialiser ce TempData dans chaque contrôleur de méthode souhaité.

    public ActionResult Index()
    {

        if (TempData["MyGlobalVariable"] == null)
            return RedirectToAction("MyGlobalVariableInitializer");
        else
            TempData["MyGlobalVariable"] =(string)TempData["MyGlobalVariable"]+" world";
     .
     .
     .
     }

dans MyGlobalVariableInitializer, vous initialisez MyGlobalVariable pour la première fois.

    public ActionResult CompanySelection()
    {
        return View();
    }


    public ActionResult MyGlobalVariableInitializer()
    {
        TempData["MyGlobalVariable"] = "Hello";
        return RedirectToAction("Index");
    }
2
Mahdi Rahmani

Comme tout le monde l'a dit, les variables globales ne fonctionneront pas. Même s'ils étaient une bonne idée, ils ne fonctionneraient pas dans un scénario de batterie de serveurs Web car la valeur ne serait que sur une seule machine.

L'action de votre contrôleur d'index pourrait ressembler à ceci ...

    public ActionResult Index()
{

    myModel myStronglyTypedModel = new myModel();

    myStronglyTypedModel.SomeStateIWantToKeep = "Hello";

    return View(myStronglyTypedModel);
}

Ensuite, dans votre impression, cela se ferait

public ActionResult Print(myModel myStronglyTypedModel)

{
    myStronglyTypedModel.SomeStateIWantToKeep += "Print";
    return View("PrintView");
}

Et votre point de vue pourrait commencer par

@ModelType myModel

et ainsi votre vue serait fortement typée.

Je suis un mec vb donc quelqu'un se sent libre de corriger mon c #. Je soupçonne que la directive @ModelType en vb est @model en c # mais je n'ai pas vérifié.

À votre santé

2
David Steele

Vous devriez probablement utiliser ViewData pour cela OR utilisez le HttpContext. ViewData ne sera valide que pour votre demande actuelle, c'est donc généralement une meilleure alternative que d'utiliser directement l'objet de session car vos données sont supprimées et non disponibles sur la demande suivante. L'utilisation de l'objet session peut présenter des problèmes de chevauchement de demandes multiples.

1