Lista de la compra mediante Session
Introducción
- Session en ASP.NET es el objeto que interacciona con las cookies, guardando y sacando datos de ellas. Las ventajas de Session es que sólo guarda los datos de un usuario, es decir, para una web customizada en la que interaccionan varios usuarios con diferentes intereses, crea una ‘experiencia’ personalizada para cada uno. Esto es capaz de lograrlo porque guarda un estado de lo que el usuario quiere, y esto no es posible en HTTP porque este no mantiene estados.
- Otra ventaja de Session respecto a otros es que este guarda los datos hasta el final de la sesión, mientras que en otros casos, por ejemplo TempData, sólo lo guardan hasta que se usan y luego los destruyen.
Caso práctico
- En este ejercicio haremos un caso práctico de Session en el que crearemos una lista de la compra para el usuario desde una base de datos que tenemos creada. Para ello necesitaremos:
- 1 base de datos
- 1 archivo LINQ to SQL.
- 1 Controller para la zona.
- 1 zona llamada Tienda con 3 vistas: Index, TiendaProductosElegidos y TiendaVista.
- 1 clase llamada Tienda.
- 2 imágenes de una cesta(una con aspa) [OPCIONAL].
- Primero debemos crear un nuevo proyecto.
- Este proyecto será del tipo Aplicación web ASP.NET -> MVC
- Para este ejemplo tenemos una base de datos creada con los datos a usar, pero puede usarse otros métodos para almacenar los datos.
- Conectamos la base de datos a nuestro proyecto.
- Crearemos un contexto con la tabla que tenemos (en la carpeta Models creamos un nuevo archivo de tipo LINQ to SQL)
- Creamos la nueva zona en Views, el controlador en Controllers y la clase en Models.
- Lo primero que editaremos será la clase Tienda. En un principio necesitaremos 2 métodos iniciales: Uno para enlazar con el contexto de la bd y así conseguir los datos de ella., y otro para crear una lista del total de productos en nuestra bd que mostraremos para que el usuario pueda elegir qué productos desea.
Clase Tienda
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- namespace VideoTutorial.Models
- {
- public class Tienda
- {
- contextoTiendaDataContext contexto;
- public Tienda()
- {
- this.contexto = new contextoTiendaDataContext();
- }
- public List GetProductos()
- {
- var consulta = from datos in contexto.PRODUCTOS
- select datos;
- return consulta.ToList();
- }
- }
- }
- En nuestra zona, vamos a la vista de Index, donde pondremos un link a nuestra página principal de compras. La segunda página no se pondrá, ya que se supone que sólo podrá ser accesible desde la principal(están comentadas para que no den conflictos con el código de la página).
Clase Producto
- @{
- ViewBag.Title = «Index»;
- }
- <h2> Index</h2>
- <ul class=»list-group»>
- <li class=»list-group-item»>@Html.ActionLink(«Productos a la venta»,»TiendaVista», «Tienda»)</li>
- </ul>
- La página principal tendrá que tener un código donde cargue dinámicamente los productos que poseemos en la bd, además de darle la opción de poder seleccionar el producto que desee añadir a su cesta (como en este caso es una lista de videojuegos, debemos dejar que el cliente pueda seleccionar varias veces el mismo producto) y una zona donde se muestre el total de productos y precio que lleva en su cesta. Para terminar habrá un botón que le envíe a la siguiente vista.
Clase Producto
- @{
- ViewBag.Title = «TiendaVista»;
- }
- @model List
- <h2>Productos a la venta</h2>
- <hr />
- <table border=»1″ class=»table-bordered»>
- <tr>
- <th>Nombre juego</th>
- <th>Precio</th>
- <th></th>
- </tr>
- @foreach (var prod in Model)
- {
- <tr>
- <td>@prod.NPRODUCTO</td>
- <td>@prod.PRECIO €</td>
- <td>
- <a href=’@Url.Action(«TiendaVista», «Tienda», new { producto = prod.IDPRODUCTO, precio=prod.PRECIO }, null)’>
- <img src=’@Url.Content(«~/Images/carrito.jpg»)’ height=»30″ width=»30″ />
- </a>
- </td>
- </tr>
- }
- </table>
- <br />
- @if (ViewBag.TotalProductos != null && ViewBag.PrecioTotal != null)
- {
- <table class=»table-responsive, table-bordered»>
- <tr>
- <th>Total productos</th>
- <th>Precio Total</th>
- </tr>
- <tr>
- <td>@ViewBag.TotalProductos</td>
- <td>@ViewBag.PrecioTotal</td>
- </tr>
- </table>
- }
- <button type=»button» onclick=»location.href=’@Url.Action(«TiendaProductosElegidos», «Tienda»)'» class=»btn-success»>
- Comprar
- </button>
- Iremos al controlador y crearemos un public para el modelo (incluyendo el using de Models).
Clase Producto
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
- using VideoTutorial.Models;
- namespace VideoTutorial.Controllers
- {
- public class TiendaController : Controller
- {
- Tienda modelo;
- public TiendaController()
- {
- this.modelo = new Tienda();
- }
- // GET: Tienda
- public ActionResult Index()
- {
- return View();
- }
- }
- }
- Después crearemos un get para la nueva vista. Tenemos que tener en cuenta que habrá dos «procesos»: El cargar la página por primera vez (sin un producto seleccionado) y cuando el usuario seleccione un producto deseado.
Clase Producto
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
- using VideoTutorial.Models;
- namespace VideoTutorial.Controllers
- {
- public class TiendaController : Controller
- {
- Tienda modelo;
- public TiendaController()
- {
- this.modelo = new Tienda();
- }
- // GET: Tienda
- public ActionResult Index()
- {
- return View();
- }
- public ActionResult TiendaVista(int? producto, decimal? precio)
- {
- List listaproductos = this.modelo.GetProductos();
- decimal suma = 0;
- if (producto != null && precio != null)
- {
- //aquí tenemos el id de un producto y su precio. queremos almacenar múltiples
- List idproductos;
- List precios;
- if (Session[«PRODUCTOS»] == null)
- {
- //si no existe creamos la colección
- idproductos = new List();
- precios = new List();
- }
- else
- {
- //si existe, recuperamos la colección de la sesión
- idproductos = (List)Session[«PRODUCTOS»];
- precios = (List)Session[«PRECIOS»];
- }
- //añadimos el nuevo id en la colección con su precio
- idproductos.Add(producto.GetValueOrDefault());
- precios.Add(precio.GetValueOrDefault());
- Session[«PRODUCTOS»] = idproductos;
- Session[«PRECIOS»] = precios;
- //como es una lista de la compra, los precios deben sumarse a un total
- for (int i = 0; i < precios.Count(); i++)
- {
- suma += precios[i];
- }
- //devolvemos el total productos y el total precio por viewbag
- ViewBag.PrecioTotal = suma + «€»;
- ViewBag.TotalProductos = idproductos.Count();
- }
- //devolvemos siempre la lista de productos
- return View(listaproductos);
- }
- }
- }
- El usuario debería poder ver un listado de nuestros productos y almacenar el Session los que él desee haciendo click sobre la imagen de la cesta.
- El siguiente paso es crear el código de la vista de confirmación de la compra, en la que deberemos visualizar los productos que el usuario ha seleccionado con la opción a cancelar alguno o todos, además de un mensaje de alerta por si la lista está vacía.
Clase Producto
<
- >
- @{
- ViewBag.Title = «TiendaProductosElegidos»;
- }
- @model List
- <h2> Lista de la compra</h2>
- @if (Session[«PRODUCTOS»] == null)
- {
- //La lista de la compra está vacía
- <h2 class=»text-danger»> Su lista de la compra está vacía</h2>
- }
- <hr />
- @if (Model != null)
- {
- <table class=»table-bordered»>
- <tr>
- <th> Nombre juego</th>
- <th> Precio</th>
- <th> </th>
- </tr>
- @foreach (var prod in Model)
- {
- <tr>
- <td> @prod.NPRODUCTO</td>
- <td> @prod.PRECIO €</td>
- <td>
- <a href=’@Url.Action(«TiendaProductosElegidos», «Tienda», new { borrarproducto = prod.IDPRODUCTO, borrarprecio=prod.PRECIO }, null)’>
- <img src=’@Url.Content(«~/Images/delete.png»)’ height=»30″ width=»30″ />
- </a>
- </td>
- </tr>
- }
- </table>
- }<br />
- @if (ViewBag.TotalProductos != null && ViewBag.PrecioTotal != null)
- {
- <table class=»table-bordered»>
- <tr>
- <th> Total productos</th>
- <th> Precio Total</th>
- </tr>
- <tr>
- <td> @ViewBag.TotalProductos</td>
- <td> @ViewBag.PrecioTotal</td>
- </tr>
- </table>
- }
- <button type=»button» onclick=»location.href=’@Url.Action(«TiendaVista», «Tienda»)'» class=»btn-warning»>
- Volver
- </button>
- Como vamos a dar la opción a eliminar productos de su lista, debemos crear un nuevo método en la clase Tienda donde busquemos en la lista creada el producto concreto.
Clase Tienda
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- namespace VideoTutorial.Models
- {
- public class Tienda
- {
- contextoTiendaDataContext contexto;
- public Tienda()
- {
- this.contexto = new contextoTiendaDataContext();
- }
- public List GetProductos()
- {
- var consulta = from datos in contexto.PRODUCTOS
- select datos;
- return consulta.ToList();
- }
- public List GetProductosSesion(List idproductos)
- {
- var consulta = from datos in contexto.PRODUCTOS
- where idproductos.Contains(datos.IDPRODUCTO)
- select datos;
- return consulta.ToList();
- }
- }
- }
- Ahora vamos al Controller y creamos el Get para la 2ª página. Como en el anterior, deberemos tener en cuenta varios casos: que haya o no productos, si los hay cargarlos todos y si cancela alguno, quitarlo de la lista.
Clase Producto
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
- using VideoTutorial.Models;
- namespace VideoTutorial.Controllers
- {
- public class TiendaController : Controller
- {
- Tienda modelo;
- public TiendaController()
- {
- this.modelo = new Tienda();
- }
- // GET: Tienda
- public ActionResult Index()
- {
- return View();
- }
- public ActionResult TiendaVista(int? producto, decimal? precio)
- {
- List listaproductos = this.modelo.GetProductos();
- decimal suma = 0;
- if (producto != null && precio != null)
- {
- //aquí tenemos el id de un producto y su precio. queremos almacenar múltiples
- List idproductos;
- List precios;
- if (Session[«PRODUCTOS»] == null)
- {
- //si no existe creamos la colección
- idproductos = new List();
- precios = new List();
- }
- else
- {
- //si existe, recuperamos la colección de la sesión
- idproductos = (List)Session[«PRODUCTOS»];
- precios = (List)Session[«PRECIOS»];
- }
- //añadimos el nuevo id en la colección con su precio
- idproductos.Add(producto.GetValueOrDefault());
- precios.Add(precio.GetValueOrDefault());
- Session[«PRODUCTOS»] = idproductos;
- Session[«PRECIOS»] = precios;
- //como es una lista de la compra, los precios deben sumarse a un total
- for (int i = 0; i < precios.Count(); i++)
- {
- suma += precios[i];
- }
- //devolvemos el total productos y el total precio por viewbag
- ViewBag.PrecioTotal = suma + «€»;
- ViewBag.TotalProductos = idproductos.Count();
- }
- //devolvemos siempre la lista de productos
- return View(listaproductos);
- }
- public ActionResult TiendaProductosElegidos(int? borrarproducto, decimal? borrarprecio)
- {
- //recuperamos las listas de la sesión que se han creado en la página principal
- List idproductos = (List)Session[«PRODUCTOS»];
- List precios = (List)Session[«PRECIOS»];
- decimal suma = 0;
- if (borrarproducto != null)
- {
- //si el usuario ha deseado cancelar un producto de la lista entra aquí
- //y recuperamos el valor
- idproductos.Remove(borrarproducto.GetValueOrDefault());
- precios.Remove(borrarprecio.GetValueOrDefault());
- if (idproductos.Count() == 0)
- {
- //si ya no hay productos en la lista, ponemos todo a null
- Session[«PRODUCTOS»] = null;
- Session[«PRECIOS»] = null;
- ViewBag.PrecioTotal = null;
- ViewBag.TotalProductos = null;
- }
- else
- {
- //si la lista aún no está vacía, recuperamos el resto
- Session[«PRODUCTOS»] = idproductos;
- Session[«PRECIOS»] = precios;
- }
- }
- if (Session[«PRODUCTOS»] != null)
- {
- //si existe contenido en la sesión lo recuperamos
- //recuperamos los productos y su precio a partir de la colección
- List listaproductos = this.modelo.GetProductosSesion(idproductos);
- //volvemos a hacer una suma total de precios de los
- //productos que estén en la colección
- for (int i = 0; i < precios.Count(); i++)
- {
- suma += precios[i];
- }
- //volvemos a enviar los ViewBag
- ViewBag.PrecioTotal = suma + «€»;
- ViewBag.TotalProductos = idproductos.Count();
- return View(listaproductos);
- }
- return View();
- }
- }
- }
- Así sería como quedaría la página de la lista.