TempData sin variables de sesión en MVC - Code Variables -->
Code Variables Code Variables

Latest news

جاري التحميل ...

TempData sin variables de sesión en MVC

ASP.NET MVCEn ASP.NET MVC, TempData es un mecanismo de lo más socorrido cuando se pretende hacer persistir información entre distintas peticiones de forma sencilla.
Hace ya bastante tiempo hablamos por aquí de cómo funciona, aunque resumidamente podríamos decir que se trata de un almacén temporal en el que podemos guardar datos desde una acción y consultarlos desde otra, aunque sea en peticiones distintas; la información se quedará almacenada hasta que sea obtenida por primera vez, momento en el que será eliminada del repositorio utilizado.

El principal problema que encontramos al utilizarlo en proyectos reales es que la información se guarda en variables de sesión, lo que en determinados escenarios puede ser muy costoso o simplemente imposible, y esto hace que descartemos su uso y que tengamos que inventar alternativas para solucionar problemas que usando TempData ya tendríamos resueltos.

Sin embargo, el hecho de que se utilicen variables de sesión, como casi todo en el framework, es simplemente un comportamiento por defecto que puede ser reemplazado por otro. Podríamos guardar la información de TempData en una base de datos, archivos de texto o cualquier otro lugar donde nos interese hacerlo :-)

Y lo que vamos a ver en este post es una implementación muy sencilla para hacer persistir esta información en cookies. Así, cuando desde el servidor establezcamos un valor en el TempData, lo que haremos es enviárselo en una cookie al cliente, donde persistirá hasta que sea leído. Obviamente no se puede usar para guardar datos confidenciales ni nada parecido, ni tampoco es interesante para gran cantidad de datos puesto que éstos viajarán entre cliente y servidor hasta ser eliminados, pero puede ser útil en escenarios simples y creo que ilustra bastante bien el funcionamiento interno de esta interesante característica de ASP.NET MVC.

TempData Providers

Todos los controladores tienen una propiedad llamada TempDataProvider, que es la encargada de suministrar el componente que se encargará de guardar y recuperar información. En su interior se encuentra un objeto que implementa el interfaz ITempDataProvider, cuya definición vemos a continuación:
public interface ITempDataProvider
{
IDictionary<string, object> LoadTempData(ControllerContext controllerContext);
void SaveTempData(ControllerContext controllerContext,
IDictionary<string, object> values);
}
Cuando el framework carga el controlador, antes de invocar la acción correspondiente llamará al método TempDataProvider.LoadTempData() para obtener la información salvada desde el almacén correspondiente y cargarla en el diccionario TempData.

De la misma forma, al finalizar el proceso de la acción, ASP.NET MVC ejecutará el método TempDataProvider.SaveTempData() para volcar la información almacenada en el diccionario  TempData al sistema de persistencia elegido.

Decíamos antes que por defecto se utilizan variables de sesión, ¿verdad? Pues esto se debe a que internamente en TempDataProvider encontraremos inicialmente una instancia de SessionStateTempDataProvider, cuya implementación lo único que hace es utilizar variables de sesión para almacenar y obtener la información.

Para modificar este comportamiento lo único que tenemos que hacer es crear una clase que implemente ese sencillo interfaz, e introducir un objeto de este nuevo tipo en la propiedad TempDataProvider de los controladores. Fácil, ¿eh?

Un TempDataProvider para cookies

El siguiente código muestra la implementación de nuestro flamante CookieTempDataProvider. Observad que aprovechamos el método SaveTempData() para serializar en JSON el contenido del diccionario TempData, y el método LoadTempData() para realizar la operación inversa:
public class CookieTempDataProvider : ITempDataProvider
{
private const string CookieName = "_TempData_";

public IDictionary<string, object> LoadTempData(
ControllerContext controllerContext)
{
var cookie = controllerContext.HttpContext.Request.Cookies.Get(CookieName);
if (cookie != null)
{
return Newtonsoft.Json.JsonConvert
.DeserializeObject<Dictionary<string, object>>(cookie.Value);
}
return null;
}

public void SaveTempData(ControllerContext controllerContext,
IDictionary<string, object> values)
{
if (values != null && values.Any())
{
var serializedData = Newtonsoft.Json.JsonConvert.SerializeObject(values);
var cookie = new HttpCookie(CookieName, serializedData);
controllerContext.HttpContext.Response.Cookies.Add(cookie);
}
else
{
var cookie = controllerContext.HttpContext.Request.Cookies[CookieName];
if (cookie != null)
{
cookie.Expires = DateTime.Now.AddDays(-1);
controllerContext.HttpContext.Response.Cookies.Set(cookie);
}
}
}
}
El código de SaveTempData() es un poco más extenso porque estamos incluyendo la lógica para eliminar la cookie cuando ya no sea necesaria, es decir, cuando no haya información almacenada en TempData.

Por supuesto, podríamos habernos parado un poco más en la creación de la cookie y definirla más detalladamente, por ejemplo estableciéndole la caducidad, visibilidad, etc., pero no es ese el objetivo en este momento…

Modificar el proveedor de TempData por defecto

Ya lo único que nos queda es introducir este nuevo proveedor en el pipeline de ASP.NET MVC. Esto tenemos varias formas de hacerlo, vamos a ver dos de ellas.

Una forma muy sencilla es establecer el TempDataProvider desde los propios controladores, o bien desde una de sus clases base para no tener que repetir demasiado ese código. En este caso, podemos aprovechar que para instanciar estos proveedores el framework invoca al método virtual CreateTempData() del controlador; basta con sobrescribirlo y tenemos ya todo el trabajo hecho:
public class BaseController: Controller
{
protected override ITempDataProvider CreateTempDataProvider()
{
return new CookieTempDataProvider();
}
}

public class HomeController : BaseController
{
// We are now using the CookieTempDataProvider
...
}
Aún más fácil resulta si estamos utilizando un contenedor de inversión de control como Unity o Ninject. En este caso, bastará con asociar el interfaz ITempDataProvider a nuestra clase y todo saldrá funcionando como por arte de magia, puesto que el Dependency Resolver es utilizado de forma interna para crear el proveedor.

El siguiente código sería el registro usando Unity:
container.RegisterType<ITempDataProvider, CookieTempDataProvider>();
Con cualquiera de estas dos técnicas ASP.NET MVC pasaría a utilizar cookies para persistir la información del TempData. Si en lugar de cookies preferís otro sitio simplemente habría que crear otro proveedor e implementar los métodos LoadTempData() y SaveTempData() para tenerlo resuelto.

¿Sencillo, eh?

Publicado en: Variable not found.

Comments



If you like the content of our blog, we hope to stay in constant communication, just enter your email to subscribe to the blog's express mail to receive new blog updates, and you can send a message by clicking on the button next ...

إتصل بنا

About the site

author Code Variables  Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

Learn more ←

Blog visitors

Blog stats

All Copyrights Reserved

Code Variables

2019