2011-05-09 24 views
14

Estoy desarrollando una aplicación web ASP.NET MVC 3 utilizando Razor y C#.¿Cómo se mantiene el valor de las variables globales entre las diferentes llamadas a métodos de acción en MVC3?

Acabo de descubrir que tengo algunos problemas con las variables globales, probablemente porque soy relativamente nuevo en MVC.

Tengo un controlador con algunas variables globales y métodos de acción. Decidí una variable global para permitir que los métodos de acción la manipularan y reflejara las manipulaciones de todos los métodos de acción. Tengo la siguiente situación:

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

El método de acción Imprimir() se llama con un Html.ActionLink() del MyView Vista.

Lo sorprendente es que el valor de _MyGlobalVariable no se cumple. Por lo tanto, el valor de _MyGlobalVariable antes de la instrucción _MyGlobalVariable += "Print" es igual a nulo.

¿Estoy cometiendo un error? ¿Cómo puedo mantener el valor de las variables globales entre llamadas a Vistas?

Gracias

Francesco

PD: en mi caso específico de la variable global es una Dictionary<K,V> pero supongo que no cambia la lógica.

PPS: Sé que usted puede utilizar ViewModels en lugar de variables globales para pasar los datos entre los métodos de acción, pero en mi caso es mucho menos código si uso un Dictionary<K,V> que por lo general no me envuelvo en ViewModels (utilizo POCOs o Lists<T>)

+2

No haga esto. ¿Que estás tratando de hacer? – SLaks

+0

@SLaks: Tengo algunos valores en un diccionario . Tengo que mostrarlos en una tabla y para hacerlo, envuelvo todos los elementos del Diccionario en un ViewModel. En la vista, el usuario tiene la tabla y tiene que confirmar a través de ActionLink si los datos están correctos. Luego, el método de acción señalado por ActionLink realiza la actualización de datos. El problema es que utilizo la clave del diccionario para actualizar los valores, por lo que pasar el modelo de vista al método de acción de actualización no sería tan útil. Espero haber sido claro – CiccioMiami

+0

Sí, cuéntanos qué intentas lograr. Las variables globales en ASP.NET MVC generalmente son un no-no, pero tal vez puedas usar algo tan simple como TempData. Depende de tu objetivo aunque – Francisco

Respuesta

27

Cada solicitud recibe una nueva instancia de controlador.
Dado que su "variable" es un campo de instancia, no persiste.

Puede solucionarlo haciéndolo static, o utilizando el estado de la aplicación.

Sin embargo, no.
Nunca debe usar el estado global mutable en una aplicación web.

En particular, si obtiene dos solicitudes al mismo tiempo, su campo se arruinará.

Dependiendo de lo que esté tratando de hacer, es posible que desee utilizar el estado de sesión o las cookies.

+0

gracias por su respuesta. ¿Es correcto usar cookies o Session en mi caso? Tengo algunos valores en un diccionario . Tengo que mostrarlos en una tabla y para hacerlo, envuelvo todos los elementos del Diccionario en un ViewModel. En la vista, el usuario tiene la tabla y tiene que confirmar a través de ActionLink si los datos están correctos. Luego, el método de acción señalado por ActionLink realiza la actualización de datos. El problema es que utilizo la clave del diccionario para actualizar los valores, por lo que pasar el modelo de vista al método de acción de actualización no sería tan útil. – CiccioMiami

3

Antes que nada, no existen variables globales en C#. Lo que estás buscando es una variable estática, a la que se puede acceder a través de una clase. Como se crea una nueva instancia de controlador en cada solicitud, el valor de su variable se pierde.

Tendrá que declarar la variable como tal:

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

y acceder a ella como tal:

MyControllerClass._MyGlobalVariable 

Además, esta variable sólo será accesible desde métodos de la clase myController, como lo has declarado privado.

Además de esto, es probable que desee bloquear la variable cada vez que la utilice, ya que finalmente terminará corriendo en condiciones de carrera.

nota: no recomendaría hacerlo de esta manera

+1

No recomendaría el uso de "variables" estáticas en una aplicación web. Ver la respuesta de Slaks – Francisco

+0

Estoy de acuerdo, pero esto es técnicamente lo que estaba tratando de hacer. –

+0

gracias por su respuesta. Vengo de C++, así que tengo el hábito de llamar variables estáticas visibles de toda la clase como variables globales (muchos desarrolladores todavía usan esta convención). Perdón si eso te confundió – CiccioMiami

1

Probablemente debería utilizar para este ViewData O utilizar el HttpContext. ViewData solo será válido para su solicitud actual, por lo que generalmente es una mejor alternativa que usar directamente el objeto de sesión ya que sus datos se eliminan y no están disponibles en la próxima solicitud. El uso del objeto de sesión puede sufrir problemas de superposición de solicitudes múltiples.

2

Como todos dijeron que las variables globales aquí no funcionarán. Incluso si fueran una buena idea, entonces no funcionarían en un escenario de granja web ya que el valor sería solo en una máquina.

Su Índice de acción del controlador podría ser algo como esto ....

public ActionResult Index() 
{ 

    myModel myStronglyTypedModel = new myModel(); 

    myStronglyTypedModel.SomeStateIWantToKeep = "Hello"; 

    return View(myStronglyTypedModel); 
} 

A continuación, en su impresión haría esto

public ActionResult Print(myModel myStronglyTypedModel) 

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

Y su punto de vista podría podría comenzar con

@ModelType myModel 

por lo que su vista se escribiría fuertemente.

Soy un chico vb así que alguien puede corregir mi C#. Sospecho que la directiva @ModelType en vb es @model en C# pero no ha marcado.

Saludos

1

podrá usar el diccionario TempData para guardar un paso controlador llamando. TempData envía sus datos a solo una próxima sesión. Si desea conservar sus datos en todas las sesiones, debe inicializar ese TempData en cada controlador de método que desee.

public ActionResult Index() 
    { 

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

en MyGlobalVariableInitializer, inicializar MyGlobalVariable por primera vez.

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


    public ActionResult MyGlobalVariableInitializer() 
    { 
     TempData["MyGlobalVariable"] = "Hello"; 
     return RedirectToAction("Index"); 
    } 
+0

Gracias Mahdi jan :) – Hamid

Cuestiones relacionadas