TempData en ASP.NET MVC 2

ASP.NET MVC 2TempData es un diccionario disponible a nivel de controladores y vistas del framework ASP.NET MVC que nos permite almacenar objetos de forma similar a la colección ViewData, pero, a diferencia de ésta, es capaz de mantener su contenido entre peticiones.

De hecho, es un recurso habitualmente utilizado cuando necesitamos enviar información desde una acción a otra tras realizar una redirección. Por ejemplo, ante una petición dirigida hacia la acción “Milestone” en un controlador como el siguiente:

public ActionResult Milestone() 
{
  TempData["Message"] = "He pasado por aquí";
  RedirectToAction("ShowMessage");
}
 
public ActionResult ShowMessage()
{
  return View();
} 

… podríamos tener en la plantilla de vista ShowMessage.aspx acceso directo a la entrada del TempData almacenada en la petición que inició la secuencia:

<p class="msg"><strong><%= TempData["Message"] %></strong></p>

Pues bien, la beta de ASP.NET MVC 2 introdujo en el comportamiento de este diccionario una serie de cambios que merecen ser comentados.

En primer lugar, ha sido modificado el ciclo de vida de las entradas existentes en el TempData. Ahora cada elemento del diccionario es analizado al finalizar la ejecución del controlador (concretamente su método ExecuteCore()); aquellos que estén “marcados” continuarán viviendo en el mecanismo de persistencia elegido (por defecto, en una variable de sesión del usuario) y el resto serán eliminados sin piedad.

Internamente se procede de la siguiente manera: al comenzar el proceso de la petición, se cargan en la propiedad TempData del controlador los valores almacenados en el proveedor de datos temporales,  un objeto que implementa el interfaz ITempDataProvider. La implementación por defecto utiliza la clase SessionStateTempDataProvider para almacenar la información en  la variable de sesión “__ControllerTempData”.

En este momento, todas las entradas presentes en el diccionario son marcadas como candidatas a ser conservadas.To be or not to be...

Si desde cualquier punto del código del controlador o la vista se obtiene el valor de una entrada del diccionario, como en el ejemplo de vista ShowMessage anteriormente mostrado, se eliminará la marca de supervivencia y pasarán a estar en la cuerda floja.

Al finalizar la ejecución del controlador, se recorren aquellas entradas del diccionario que no estén marcadas y se eliminan del diccionario. Finalmente, éste es salvado a través del proveedor de datos temporales actual.

Sólo hay una excepción para el caso anterior: las redirecciones. Éstas, en su método ExecuteResult(), incluyen una llamada al método Keep() del diccionario TempData actual, lo que provoca que todas las entradas del mismo sean marcadas para su conservación. Por tanto, una acción que retorne un tipo RedirectToRouteResult, siempre conservará el TempData intacto.

Como consecuencia, una forma de evitar la eliminación de una entrada y forzar su conservación al finalizar la petición actual es utilizando TempData.Keep(key), siendo key la clave de la misma,  o generalizando como en el caso anterior, TempData.Keep(), que salvará todas las entradas almacenadas.

Pero ojo, que esto puede provocar un efecto no deseado. Dado que por defecto las entradas al diccionario no van a eliminarse salvo que sean leídas, puede dar lugar a contenidos perennes en el estado de sesión del usuario. O en otras palabras, si introducimos en TempData una entrada con un objeto pesado y éste nunca es obtenido, permanecerá en la sesión del usuario hasta que ésta desaparezca… supongo que no es necesario comentar lo desastroso que puede ser esto, no? ;-D

Otro aspecto curioso es que cualquier consulta al TempData hará que la entrada sea marcada para su eliminación… incluso si estamos consultándola desde el depurador de Visual Studio. Por tanto, cuidado con esto, que puede provocar algún dolor de cabeza.

Aunque algo denostado, TempData sigue siendo una opción válida para el traspaso de información entre distintas peticiones, aunque siempre usado con moderación y sentido común. 

Publicado en: Variable not found.
Hey, ¡estoy en twitter!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *