Saltar al contenido

Tutorial de ASP.NET MVC – Vinculación de datos y vistas jerárquicas

El proyecto Blip.Web de la solución BlipBinding se basa en la plantilla estándar del MVC del .NET Framework, por lo que la disposición de las vistas se basa en el estilo CSS de Bootstrap por defecto y en el _layout.cshtml incluido en la plantilla.

A los efectos de la presente guía, hay dos puntos de vista notables en el estudio de casos, uno para mostrar una lista de clientes y otro para mostrar una lista de pedidos para cada cliente.

Tutorial de ASP.NET MVC – Vinculación de datos y vistas jerárquicas
Tutorial de ASP.NET MVC – Vinculación de datos y vistas jerárquicas

Vista del cliente/índice

La vista de la lista de clientes es una simple tabla que muestra alguna información básica sobre el cliente y un método de ayuda Html.ActionLink para navegar a la lista de pedidos del cliente:

Solución BlipBinding, proyecto Blip.Web, vista Cliente/Índice

Utilizando el método Seed de migraciones de código de Entity Framework, hemos llenado la base de datos con algunos clientes, pedidos y artículos. Si ejecuta la solución de ejemplo, la aplicación creará la base de datos y agregará los mismos registros (los GUID creados por su computadora para los campos clave serán diferentes de los que se muestran).

Blip.WebVistasNde cliente.cshtml

En el código de la vista anterior, observe que la lista de clientes se crea con un bucle previo que se itera a través de la colección de entidades CustomerDisplayViewModel. Esta es una forma estándar de presentar una lista con un número variable de registros:

1234567891011121314151617181920@foreach(var item in Model){<tr><td> @Html.DisplayFor(modelItem => item.CustomerID)</td><td> @Html.DisplayFor(modelItem => item.CustomerName)</td>td> @Html. DisplayFor(modelItem => item.CountryName)</td><td> @Html.DisplayFor(modelItem => item.RegionName)</td>td> @Html.ActionLink("Orders", "Index", "Order",new{ customerid = item.CustomerID },null)</td>/tr>}

csharp

En la lista de clientes, el modelo de vista tiene una estructura plana, es sólo una lista enumerable de objetos que contienen la información del cliente. Aquí está la directiva @model del principio de Index.cshtml:

1@modelo IEnumerable<Blip.Entidades.Clientes.VerModelos.ClienteVisualizarModelo;

csharp

Ahora veamos más de cerca ese modelo de vista.

Blip.EntitiesClientes.ViewModelsNVisualización de clientesViewModel.cs

1234567891011121314151617181920 usando el sistema;usando el sistema.ComponenteModelo.DatosAnotados;espacio.de.nombres.de.entidades.de.Blip.Clientes. ViewModels{publicclassCustomerDisplayViewModel{[Display(Name ="Número de Cliente")]publicGuid CustomerID {get;set;}[Display(Name ="Nombre del Cliente")]publicstring CustomerName {get;set;}[Display(Name ="País")]publicstring CountryName {get;set;}[Display(Name ="State / Province / Region")]publicstring RegionName {get;set;}}

csharp

Observe que estamos usando anotaciones de datos en el modelo de la vista para proporcionar las etiquetas de campo para mostrar en la vista.

Cuando el método de repositorio rellena este modelo combina datos de la tabla Customers con CountryNameEnglish de la tabla Country y RegionName de la tabla Region . De esta manera, el modelo de vista puede presentar información más útil para el usuario que los valores de índice para el país y la región de la tabla Customers .

Vista de orden/índice

La simple lista de pedidos para un cliente muestra la información del cliente y el número y la fecha del pedido como campos de sólo lectura, y el pedido/descripción de compra como un campo editable. Cambiando los valores en el campo editable y guardando podemos ver cómo funciona la vinculación del modelo al hacer acciones HttpPost.

Solución BlipBinding, proyecto Blip.Web, vista Orden/Índice

En esta visión, presentamos la información en una estructura jerárquica. En el nivel superior está la información del cliente. Debajo de eso está la lista de pedidos para el cliente.

Veamos cómo se presentan los datos en código.

Blip.WebVistasN-PedidoN-Índice.cshtml

Para los datos de primer nivel, relativos al cliente, los campos se componen de una manera muy estándar:

123456<div @Html.LabelFor(model => model.CustomerName,new{ @})<div @Html.EditorFor(model => model.CustomerName,new{ htmlAttributes =new{ @, @readonly="readonly"}})</div></div>

csharp

Note que estamos usando el EditorFor HtmlHelper para que el motor Razor determine el tipo correcto de elemento HTML para el tipo de datos. También estamos aplicando la clase CSS de control de formulario para asegurarnos de que el control recoge el estilo apropiado. El campo se cambia de un cuadro de texto editable a un campo de sólo visualización con la aplicación del atributo @readonly HTML.

Para los datos del segundo nivel, la lista de pedidos, estamos repasando los registros en el modelo de vista. Pero en este caso estamos no usando un bucle foreach y estamos no usando el EditorPara HtmlHelper. Veremos las razones de estas elecciones con más detalle en la sección de guardar datos.

123456789101112131415161718@if(Model.Orders !=null){for(var i =0; i < Model.Orders.Count(); i++){<tr> @Html.HiddenFor(x => Model.Orders[i].CustomerID)<td> @Html.TextBoxFor(x => Model.Orders[i]. OrderID,new{ @, @readonly="readonly"})</td><td> @Html.TextBoxFor(x => Model.Orders[i]. OrderDate,new{ @, @readonly="readonly"})</td><td> @Html.TextBoxFor(x => Model.Orders[i].Description,new{ @})</td></tr>}}}

csharp

También notará que estamos usando un bucle for con una variable de conteo en lugar de un bucle foreach. Esto es crucial para conseguir que funcione la acción $0027HttpPost$0027, como veremos pronto.

Blip.EntidadesNPedidos.VerModelosN-Pedidos de ClientesVerModelo.cs

El modelo de vista para los pedidos de los clientes refleja la estructura jerárquica de la vista que se muestra arriba. Reúne la información de visualización sobre el cliente a partir de las tablas Clientes , Países y Regiones e incluye una propiedad que es una colección de entidades OrderDisplayViewModel.

1234567891011121314151617181920212223usando System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;namespace Blip.Entities Orders. ViewModels{publicclassCustomerOrdersListViewModel{[Display(Name ="Customer Number")]publicGuid CustomerID {get;set;}[Display(Name ="Customer Name")]publicstring CustomerName {get;set; }[Mostrar(Nombre ="País")]publicstring CountryNameEnglish {get;set;}[Mostrar(Nombre ="Región")]publicstring RegionNameEnglish {get;set;}public List<OrderDisplayViewModel> Orders {get;set;}}}

csharp

Echemos un vistazo a la clase que compone la colección de las Órdenes.

Blip.EntidadesNPedidos.VerModelosN-PedirVerModelo.cs

Tenga en cuenta que cada entidad en OrderDisplayViewModel está vinculada al cliente asociado en CustomerOrdersListViewModel. Cuando transponemos las entidades a la estructura del modelo de vista, necesitamos preservar la relación entre las entidades (y las tablas de la base de datos).

12345678910111213141516171819usando Sistema;usando Sistema.ComponenteModelo.DatosAnotados;espacio.de.nombres.de.Entidades.Blip. ViewModels{publicclassOrderDisplayViewModel{publicGuid CustomerID {get;set;}[Display(Name ="Order Number")]publicGuid OrderID {get;set;}[Display(Name ="Order Date")]publicDateTime OrderDate {get;set;}[Display(Name ="PO / Description")]publicstring Description {get;set;}}

csharp

Obsérvese también que no hay propiedades virtuales en ninguna de estas clases para proporcionar la navegación entre entidades. Los modelos de vista sirven al propósito funcional de la vista y están desacoplados de las relaciones de entidad de las clases y de las tablas de la base de datos. Por consiguiente, cuando se utilizan dos modelos de vista juntos, reflejan la relación o relaciones entre los modelos de vista, en lugar de las entidades de las que se extraen los datos.

Los métodos de reposición se encargan de transponer los datos de la estructura de las entidades a la estructura de los modelos de vista y viceversa.

Acción del controlador de órdenes para el índice HttpGet

Usando MVVM y el patrón de diseño del repositorio, podemos hacer que las acciones de nuestro controlador sean sucintas y proporcionar la separación de las preocupaciones entre la capa de presentación, la lógica de negocio y los datos. Podemos ver eso en la acción en la acción del controlador que puebla la vista Orden/Índice .

Blip.WebNcontroladoresNde orden de control.cs

12345678910111213141516171819202122232425usando Sistema;usando Sistema.Net;usando Sistema.Web.Mvc;usando Blip.Datos.Órdenes;usando Blip.Entidades.Órdenes.VerModelos;espacio de nombres BlipProyectos.Controladores{clase públicaControlador de Órdenes:Controlador{// GET: OrderpublicActionResultadoIndex(string customerid){if(!String.IsNullOrWhiteSpace(customerid)){if(Guid.TryParse(customerid,outGuid customerId)){var repo =newOrdersRepository();var model = repo. GetCustomerOrdersDisplay(customerId);returnView(model);}}returnnewHttpStatusCodeResult(HttpStatusCode.BadRequest);}...

csharp

Todo lo que esta acción del controlador necesita hacer cuando se pasa un CustomerID de la vista Customer/Index es pasar ese valor al método de repositorio apropiado y tomar el modelo de datos resultante, una instancia de la clase CustomerOrdersListViewModel, y pasarlo a la vista.