Introducción
En el articulo aprenderemos :
- como capturar la selección de un DropDownList
- filtrar una query usando Entity Framework
- desplegar los datos en un WebGrid
La idea es listas en un dropdownlist los clientes (customers) y al seleccionar alguno, listar las ordenes de compra realizadas.
Modelo de Dominio
Empezaremos analizando el dominio de entidades que usaremos en el ejemplo.
La entidad Orden tiene relación con el cliente (customer) y un empleado (employee), usaremos el primero para filtrar mientras que el segundo será información adicional que se mostrara en una columna del grid
Definición de la persistencia
El acceso a los datos lo realizaremos con al ayuda de Entity Framework, por lo que deberemos definir el DbContext y las clases de mapping para cada entidad
public class NorthWindContext : DbContext { public NorthWindContext() : base("NorthwindDb") { Database.SetInitializer<NorthWindContext>(null); this.Configuration.LazyLoadingEnabled = false; this.Configuration.ProxyCreationEnabled = false; } public DbSet<Customer> Employees { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new CustomerMap()); modelBuilder.Configurations.Add(new EmployeeMap()); modelBuilder.Configurations.Add(new OrderMap()); modelBuilder.Configurations.Add(new LocationComplexMap()); base.OnModelCreating(modelBuilder); } } public class CustomerMap : EntityTypeConfiguration<Customer> { public CustomerMap() { HasKey(x => x.CustomerID); Property(x => x.CustomerID) .HasColumnType("nchar") .HasMaxLength(5); Property(x => x.CompanyName) .HasMaxLength(40) .IsRequired(); Property(x => x.ContactName) .HasMaxLength(30); Property(x => x.ContactTitle) .HasMaxLength(30); } } public class EmployeeMap : EntityTypeConfiguration<Employee> { public EmployeeMap() { HasKey(x => x.EmployeeID); Property(x => x.LastName) .HasMaxLength(20) .IsRequired(); ; Property(x => x.FirstName) .HasMaxLength(10) .IsRequired(); Ignore(x => x.FullName); } } public class OrderMap : EntityTypeConfiguration<Order> { public OrderMap() { HasKey(x => x.OrderID); Property(x => x.CustomerID) .HasColumnType("nchar") .HasMaxLength(5) .IsOptional(); HasOptional(x => x.Customer) .WithMany() .HasForeignKey(x => x.CustomerID); HasOptional(x => x.Employee) .WithMany() .HasForeignKey(x => x.EmployeeID); Property(x => x.ShipName) .HasMaxLength(40); Property(x => x.ShipAddress) .HasMaxLength(60); } } public class LocationComplexMap : EntityTypeConfiguration<Localization> { public LocationComplexMap() { Property(x => x.Address).HasColumnName("Address").HasMaxLength(60); Property(x => x.City).HasColumnName("City").HasMaxLength(15); Property(x => x.Region).HasColumnName("Region").HasMaxLength(15); Property(x => x.PostalCode).HasColumnName("PostalCode").HasMaxLength(10); Property(x => x.Country).HasColumnName("Country").HasMaxLength(15); } }
En este caso estamos utilizando una db existente por lo tanto importante definir la línea:
Database.SetInitializer<NorthWindContext>(null);
de esta forma indicamos que no se debe crear la db cuando ejecutemos la aplicacion
Definir datos del dropdownlist
Para la vista definiremos un modelo que nos permita especificar los datos que mostraremos al usuario.
public class CustomerOrdersModel { public SelectList CustomerList { get; set; } public List<Order> OrderList { get; set; } }
Es por eso que encontraremos dos listas, una para cargar los ítems del combo y la segunda para las ordenes del grid.
Al ingresar al action Index(), el cual responde a los pedidos GET, del controlador debemos cargar la lista del combo, nos ayudaremos con el repositorio para esta tarea.
public ActionResult Index() { CustomerOrdersModel model = new CustomerOrdersModel() { CustomerList = new SelectList(repository.GetAllWithoutSelection(), "CustomerID", "CompanyName") }; return View(model); }
la vista hará uso de las propiedades del modelo para cargar el dropdownlist
Capturar selección dropdownlist
La captura de la selección puede realizarse de varias formas, pero no debe perderse de vista que es la propiedad “name” de los controles html los que participan en el post que se realiza al servidor, no hay que confundirse con la propiedad “id” esta solo es útil para manipular el control en el cliente usando jquery.
Para capturar la acción del usuario al cambiar la selección en el dropdownlist nos ayudamos de jquery, para poder definir el selector definimos un id en el tag <form>
Es en ese momento cuando forzamos un submit para invocar a un action concreto
en el controlador encontraremos
[HttpPost] public ActionResult Index(string CustomerList) { // // usamos el metodo del repositorio el cual nos permite recuperar las odenes de compra del cliente // se incluye en esta la informacion del cliente y el empleaod que realizo la venta // var orders = orderRepository.Filter(x => x.CustomerID == CustomerList, new List<Expression<Func<Entities.Order,object>>>() { x=>x.Employee, x=>x.Customer }); CustomerOrdersModel model = new CustomerOrdersModel() { CustomerList = new SelectList(repository.GetAllWithoutSelection(), "CustomerID", "CompanyName"), OrderList = orders }; return View(model); }
El nombre del parámetro debe coincidir con la propiedad “name” del control para poder tomar el dato, en este caso hemos dejado el valor por defecto que crear asp.net mvc, pero podríamos redefinirlo.
Si en la vista cambiamos la propiedad “name” debemos también hacerlo en el parámetro del action.
Definición del WebGrid
El post al action devolverá un nuevo modelo con la lista de ordenes cargada
En la definición del grid es cuando indicamos que propiedad del modelo define los datos
var grid = new WebGrid(Model.OrderList, canPage: false, canSort: false);
luego se define el lugar donde ira el grid y que columnas se mostrara
@if (Model.OrderList != null) { @grid.GetHtml( tableStyle: "webgrid-table", headerStyle: "webgrid-head", alternatingRowStyle: "webgrid-alternating-row", selectedRowStyle: "webgrid-selected-row", columns: grid.Columns( grid.Column(columnName: "Employee.FullName", header: "Empleado", style: "webgrid-column-employee"), grid.Column(columnName: "OrderDate", header: "Fecha Pedido", format: x=>x.OrderDate.ToString("dd/MM/yyyy")), grid.Column(columnName: "RequiredDate", header: "Fecha Requisito", format: x=>x.RequiredDate.ToString("dd/MM/yyyy")), grid.Column(columnName: "ShippedDate", header: "Fecha Envio", format: x=>x.ShippedDate != null ? x.ShippedDate.ToString("dd/MM/yyyy") : ""), grid.Column(columnName: "ShipName", header: "Nombre Envio"), grid.Column(columnName: "ShipAddress", header: "Direccion Envio") )) } else { <p>No hay datos</p> }
se podría resaltar como se especifica una columna cuando la entidad esta relacionada con otra
grid.Column(columnName: "Employee.FullName", header: "Empleado", style: "webgrid-column-employee"),
al necesitar el nombre del empleado se realiza por medio de la relación
También se definió formato para las columnas fecha
grid.Column(columnName: "ShippedDate", header: "Fecha Envio", format: x=>x.ShippedDate != null ? x.ShippedDate.ToString("dd/MM/yyyy") : ""),
no solo indicando la representación de la fecha sino también validando cuando esta pueda tener un valor nulo
WebGrid referencia en asp.net mvc
Según el tipo de proyecto que crees en el Visual Studio puede que no tengas acceso al WebGrid, si este es el caso deberá agregar la referencia a la librería, para esta tarea NuGet nos dará una mano
Solo es cuestión de buscar: microsoft-web-helper
en la herramienta de nuget y proceder a instalarlo
Código
Para el ejemplo hemos utilizado Visual Studio 2012, la base de datos se encuentra en la carpeta App_Data del proyecto web
[C#]
|