Model Binding Parte 1: Seleccionando datos (ASP.NET vNext)

Este es el tercer post de la serie que estoy haciendo sobre ASP.NET vNext.

Las releases vNext de .NET  y Visual Studio incluyen toneladas de nuevas características y capacidades. Con ASP.NET vNext veremos un montón de mejoras tanto en Web Forms  como en MVC - y también en el núcleo sobre el que están construidos.

El post de hoy es el primero de tres post en los que hablaremos sobre el nuevo soporte de Model Binding que vendrá en Web Forms. Model Binding es una extensión del sistema de databinding de ASP.NET Web Forms , y ofrece un paradigma de acceso a datos centrados en el código. Hace uso de un montón de conceptos de binding que introdujimos con ASP.NET MVC - y los integra en el modelo de controles de servidor de Web Forms.

Antecedentes del Data-Binding

Mientras que los Web Forms incluyen un montón de controles datasource (p.ej: SqlDataSource, EntityDataSource, LinqDataSource) que nos permiten conectar controles de servidor declarativamente a fuentes de datos, muchos desarrolladores prefieren tener control totar sobre la lógica de acceso a datos - y escribir esta lógica usando código.

En versiones anteriores de Web Forms, esto se podía conseguir seteando la propiedad DataSource de un control directamente, y llamar al método DataBind() de la página en su code-behind. Esto funciona en la mayoría de los escenarios, sin embargo no funciona bien con controles de datos más ricos (como un GridView) que soporta operaciones automáticas como la ordenación, paginación y edición.

Otra opción disponible a día de hoy es usar el control ObjectDataSource. Este control nos permite una separación más limpia entre el código de UI y la lógica de acceso a datos, y permite a los controles de datos ofrecer funcionalidades automáticas como paginación y ordenación. Sin embargo, aunque funciona muy bien seleccionando datos, es alo engorroso cuando realizamos bindings de doble dirección, sólo soporta propiedades simples (sin binding "profundo" de tipos complejos) y normalmente hace a los desarrolladores escribir código muy complejo para estos escenarios (incluyendo escenarios comunes como validación de errores).

Introducción al Model Binding

ASP.NET vNext incluye el nuevo soporte de "Model Binding" para Web Forms.

Model Binding biene para simplificar el trabajo con el código de la lógica de acceso a datos manteniendo los beneficios de los bindings en dos direcciones. Incorpora patrón de modelo de binding que se introdujo con ASP.NET MVC , a la vez que integra el modelo de controles de servidor de Web Forms. Hace muy fácil realizar los escenarios CRUD con Web Forms - y nos permite hacerlo usando cualquier tecnología de acceso a datos (EF, Linq to SQL, NHibernate, DataSets, ADO.NET, etc).

Haré varios post esta semana sobre cómo aprovechar las nuevas características de Model Binding para obetner datos - y permitir su ordenación y paginación en un control GridView.

Obtener datos con SelectMethod

El Model Binding es una aproximación centrada en código para los data-binding. Nos permite esribir métodos helper CRUD en el code-behind de nuestra página, y enlazarlos fácilmente a controles de la página. Los controles de servidor se encargarán de llamar a los métodos en el momento apropiado en el ciclo de vida de la página y enlazar los datos.

Para ver un ejemplo sencillo de su uso, usaremos un control <asp:gridview>. El siguiente GridView tiene cuatro columnas - tres de ellas son BoundFields comunes, y el cuarto es un TemplateField. Fijáos que hemos seteado la propiedad ModelType del GridView para que sea un objeto Category - esto nos permite hacer un databinding fuertemente tipado en el TemplateField (p.ej. Item.Products.Count en lugar de usar el método Eval()):

<asp:GridView ID="categoriesGrid" runat="server" ModelType="WebApplication1.Model.Category"

    SelectMethod="GetCategories" AutoGenerateColumns="false">

    <Columns>

        <asp:BoundField DataField="CategoryID" HeaderText="ID" />

        <asp:BoundField DataField="CategoryName" HeaderText="Name" />

        <asp:BoundField DataField="Description" HeaderText="Description" />

        <asp:TemplateField HeaderText="# of Products">

            <ItemTemplate><%# Item.Products.Count %></ItemTemplate>

        </asp:TemplateField>

    </Columns>

</asp:GridView>

Hemos configurado el GridView para obtener los datos usando Model Binding seteando la propiedad SelectMethod del GridView para que apunte al método GetCategories() del code-behind de la página. El método GetCategories() tiene la siguiente pinta:

public IQueryable<Category> GetCategories() {

    var northwind = new Northwind();

    return northwind.Categories.Include(c => c.Products);

}

Estamos usando EF Code First para ejecutar una consulta LINQ que nos devuelve la lista de categorías de la base de datos de ejemplo Northwind. Fijáos que no hemos tenido que realizar la consulta de base de datos en el code-behind - podríamos haber hecho esto contra un repositorio o una capa de acceso a datos y haber usado el método helper GetCategories() para conectar el control a ella.

Cuando ejecutamos la página el GridView llamará al método anterior para obtener los datos y renderizarlos en la página de la siguiente forma:

Imagen con el resultado de la carga del GridView

Evitar selects de N+1

Os habréis dado cuenta en el código anterior es que estamos usando la extensión .Include(c=>c.Products) en la consulta LINQ. Esto le dice a EF que modifique la consulta para que además de obtener la información de la Categoría, incluya la cantidad de Products relacionados (evitando tener que hacer otra llamada a la base de datos para obenter esta información).

Soporte para la ordenanción y la paginación

Podríamos haber devuelto las categorías del méteodo GetCategories() usando un IEnumerable<Category> - o un tipo que implemente esa interfaz como un List<Category>, sin embargo, hemos devuelto las categorías usando la interfaz IQueryable<Category>:

public IQueryable<Category> GetCategories() {

    var northwind = new Northwind();

    return northwind.Categories.Include(c => c.Products);

}

Los beneficios de devolver un IQueryable<T> es que nos permite una ejecución en diferido de la consulta, y nos permite que el contorl modifique la query ántes de ejecutarla. Esto es particularmente útil con controles que soportar paginación y ordenación. Estos controles pueden añadir los operadores de paginación y ordenación en una consulta IQueryable<T> ántes de ejecutarla. Esto tiene la ventaja de hacer la ordenación y paginación realmente sencillo de implementar en vuestro código - así como aseguraros de que las operaciones de ordenación y paginación se hacen en la base de datos de una manera super eficiente.

Para habilitar la ordenación y paginación en nuestro GridView,  lo modificaremos para tener las propiedades AllowSorting y AllowPaging a true, y estableceremos el tamaño del PageSize a 5. También especificaremos una SortExpression en dos columnas:

<asp:GridView ID="categoriesGrid" runat="server" AutoGenerateColumns="false"

    AllowSorting="true" AllowPaging="true" PageSize="5"

    ModelType="WebApplication1.Model.Category"

    SelectMethod="GetCategories">

    <Columns>

        <asp:BoundField DataField="CategoryID" HeaderText="ID" SortExpression="CategoryID" />

        <asp:BoundField DataField="CategoryName" HeaderText="Name" SortExpression="CategoryName" />

        <asp:BoundField DataField="Description" HeaderText="Description" />

        <asp:TemplateField HeaderText="# of Products">

            <ItemTemplate><%# Item.Products.Count %></ItemTemplate>

        </asp:TemplateField>

    </Columns>

</asp:GridView>

Y ahora cuando ejecutemos la página, se nos mostrará ordeada y paginada:

Imágen con el gridView ordenado y paginado

Sólo se obtendrán las categorias visibles de la base de datos - ya que EF optimizará la consulta para realizar la ordenación y la paginación como parte de la consulta a la base de datos, sin hacerlo en la capa intermedia. Esto hace que la ordenación y la paginación sea realmente eficiente cuando consultamos grandes cantidades de datos.

Video de Modeling Binding y SelectMethods

Damian Edwards tiene un video de 90 segundos en el que nos muestra el uso del Model Binding para implementar un escenario con un GridView que permite la paginación y la ordenación. Podéis ver el video aquí.

Resúmen

El nuevo soporte para Model Binding en ASP.NET vNext es una evolución del sistema de data-binding de Web Forms. Toma prestados conceptos y características del sistema de Model Binding de ASP.NET MVC (veremos más en próximos posts), y hace que trabajar en paradigmas de acceso a datos sea más simple y flexible.

En próximos post de la serie extenderé el Model Binding y veremos cómo podemos integrarlo fácilmente en escenarios de filtrado, así como integrarlo también en escenarios de edición (incluyendo aquellos en los que hay que hacer validacioens).

Espero que sirva.

Scott.

Traducido por: Juan María Laó Ramos.

Artículo original

 

Deja un comentario