Recuperación y visualización de datos con formularios web y enlace de modelos

En esta serie de tutoriales se muestran aspectos básicos del uso del enlace de modelos con un proyecto de ASP.NET Web Forms. El enlace de modelos hace que la interacción de datos sea más sencilla que tratar con objetos de origen de datos (como ObjectDataSource o SqlDataSource). Esta serie comienza con material introductorio y pasa a conceptos más avanzados en tutoriales posteriores.

El patrón de enlace de modelos funciona con cualquier tecnología de acceso a datos. En este tutorial, usará Entity Framework, pero podría usar la tecnología de acceso a datos más familiar. Desde un control de servidor enlazado a datos, como un control GridView, ListView, DetailsView o FormView, especifique los nombres de los métodos que se usarán para seleccionar, actualizar, eliminar y crear datos. En este tutorial, especificará un valor para SelectMethod.

Dentro de ese método, se proporciona la lógica para recuperar los datos. En el siguiente tutorial, establecerá valores para UpdateMethod, DeleteMethod e InsertMethod.

Puede descargar el proyecto completo en C# o Visual Basic. El código descargable funciona con Visual Studio 2012 y versiones posteriores. Usa la plantilla de Visual Studio 2012, que es ligeramente diferente de la plantilla de Visual Studio 2017 que se muestra en este tutorial.

En el tutorial se ejecuta la aplicación en Visual Studio. También puede implementar la aplicación en un proveedor de hospedaje y hacer que esté disponible a través de Internet. Microsoft ofrece hospedaje web gratuito para hasta 10 sitios web en un
cuenta de evaluación gratuita de Azure. Para obtener información sobre cómo implementar un proyecto web de Visual Studio en Azure App Service Web Apps, consulte la serie ASP.NET Web Deployment using Visual Studio (Implementación web con Visual Studio). En este tutorial también se muestra cómo usar migraciones de Entity Framework Code First para implementar la base de datos de SQL Server en Azure SQL Database.

Versiones de software usadas en el tutorial

  • Microsoft Visual Studio 2017 o Microsoft Visual Studio Community 2017

Este tutorial también funciona con Visual Studio 2012 y Visual Studio 2013, pero hay algunas diferencias en la interfaz de usuario y la plantilla de proyecto.

Qué va a crear

En este tutorial, hará lo siguiente:

  • Crear objetos de datos que reflejen una universidad con estudiantes inscritos en cursos
  • Compilación de tablas de base de datos a partir de los objetos
  • Rellenado de la base de datos con datos de prueba
  • Mostrar datos en un formulario web

Creación del proyecto

  1. En Visual Studio 2017, cree un proyecto de aplicación web de ASP.NET (.NET Framework) denominado ContosoUniversityModelBinding.

    create project

  2. Seleccione Aceptar. Aparece el cuadro de diálogo para seleccionar una plantilla.

    select web forms

  3. Seleccione la plantilla Web Forms.

  4. Si es necesario, cambie la autenticación a Cuentas de usuario individuales.

  5. Seleccione Aceptar para crear el proyecto.

Modificación de la apariencia del sitio

Realice algunos cambios para personalizar la apariencia del sitio.

  1. Abra el archivo Site.Master.

  2. Cambie el título para mostrar Contoso University y no Mi aplicación ASP.NET.

    <title><%: Page.Title %> - Contoso University</title>
    
  3. Cambie el texto del encabezado de Nombre de la aplicación a Contoso University.

    <div class="navbar-header">
        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" runat="server" href="~/">Contoso University</a>
    </div>
    
  4. Cambie los vínculos de encabezado de navegación a los apropiados del sitio.

    Quite los vínculos de Acerca de y Contacto y, en su lugar, vincule a una página Students, que creará.

    <ul class="nav navbar-nav">
        <li><a runat="server" href="~/">Home</a></li>
        <li><a runat="server" href="~/Students">Students</a></li>
    </ul>
    
  5. Guarde Site.Master.

Agregar un formulario web para mostrar los datos de los alumnos

  1. En el Explorador de soluciones, haz clic con el botón derecho en el proyecto, selecciona Agregar y, después, Agregar nuevo elemento.

  2. En el cuadro de diálogo Agregar nuevo elemento, seleccione la plantilla Formulario web con página maestra y asígnele el nombre Students.aspx.

    create page

  3. Seleccione Agregar.

  4. En la página maestra del formulario web, seleccione Site.Master.

  5. Seleccione Aceptar.

Agregar el modelo de datos

En la carpeta Models, agregue una clase denominada UniversityModels.cs.

  1. Haga clic con el botón derecho en Modelos, seleccione Agregary, a continuación , Nuevo elemento. Aparecerá el cuadro de diálogo Agregar nuevo elemento.

  2. En el menú de navegación izquierdo, seleccione Códigoy, a continuación , Clase.

    create model class

  3. Asigne un nombre a la clase UniversityModels.cs y seleccione Agregar.

    En este archivo, defina las clases SchoolContext, Student, Enrollment y Course de la siguiente manera:

    using System;
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.ComponentModel.DataAnnotations;
    
    namespace ContosoUniversityModelBinding.Models
    {
        public class SchoolContext : DbContext
        {
            public DbSet<Student> Students { get; set; }
            public DbSet<Enrollment> Enrollments { get; set; }
            public DbSet<Course> Courses { get; set; }
        }
    
        public class Student
        {
            [Key, Display(Name = "ID")]
            [ScaffoldColumn(false)]
            public int StudentID { get; set; }
    
            [Required, StringLength(40), Display(Name="Last Name")]
            public string LastName { get; set; }
    
            [Required, StringLength(20), Display(Name = "First Name")]
            public string FirstName { get; set; }
    
            [EnumDataType(typeof(AcademicYear)), Display(Name = "Academic Year")]
            public AcademicYear Year { get; set; }
    
            public virtual ICollection<Enrollment> Enrollments { get; set; }
        }
    
        public class Enrollment
        {
            [Key]
            public int EnrollmentID { get; set; }
            public int CourseID { get; set; }
            public int StudentID { get; set; }
            public decimal? Grade { get; set; }
            public virtual Course Course { get; set; }
            public virtual Student Student { get; set; }
        }
    
        public class Course
        {
            [Key]
            public int CourseID { get; set; }
            public string Title { get; set; }
            public int Credits { get; set; }
            public virtual ICollection<Enrollment> Enrollments { get; set; }
        } 
    
        public enum AcademicYear
        {
            Freshman,
            Sophomore,
            Junior,
            Senior
        }
    }
    

    La clase SchoolContext deriva de DbContext, que administra la conexión de la base de datos y los cambios en los datos.

    En la clase Student, observe los atributos aplicados a las propiedades FirstName, LastName y Year. En este tutorial se usan estos atributos para la validación de datos. Para simplificar el código, solo estas propiedades se marcan con atributos de validación de datos. En un proyecto real, aplicaría atributos de validación a todas las propiedades que necesitan validación.

  4. Guarde UniversityModels.cs.

Configuración de la base de datos basada en clases

En este tutorial se usan migraciones de Code First para crear objetos y tablas de base de datos. Estas tablas almacenan información sobre los alumnos y sus cursos.

  1. Seleccione Herramientas>Administrador de paquetes NuGet>Consola del Administrador de paquetes.

  2. En la consola del Administrador de paquetes, ejecute este comando:
    enable-migrations -ContextTypeName ContosoUniversityModelBinding.Models.SchoolContext

    Si el comando se completa correctamente, aparece un mensaje que indica que se han habilitado las migraciones.

    enable migrations

    Observe que se ha creado un archivo denominado Configuration.cs. La clase Configuration tiene un método Seed, que puede rellenar previamente las tablas de base de datos con datos de prueba.

Rellenar previamente la base de datos

  1. Abra Configuration.cs.

  2. Agregue el siguiente código al método Seed. Además, añade una declaración using para el espacio de nombres ContosoUniversityModelBinding. Models.

    namespace ContosoUniversityModelBinding.Migrations
    {
        using System;
        using System.Data.Entity;
        using System.Data.Entity.Migrations;
        using System.Linq;
        using ContosoUniversityModelBinding.Models;
    
        internal sealed class Configuration : DbMigrationsConfiguration<SchoolContext>
        {
            public Configuration()
            {
                AutomaticMigrationsEnabled = false;
            }
    
            protected override void Seed(SchoolContext context)
            {
    
                context.Students.AddOrUpdate(
                     new Student { 
                         FirstName = "Carson", 
                         LastName = "Alexander", 
                         Year = AcademicYear.Freshman },
                     new Student { 
                         FirstName = "Meredith", 
                         LastName = "Alonso", 
                         Year = AcademicYear.Freshman },
                     new Student { 
                         FirstName = "Arturo", 
                         LastName = "Anand", 
                         Year = AcademicYear.Sophomore },
                     new Student { 
                         FirstName = "Gytis", 
                         LastName = "Barzdukas", 
                         Year = AcademicYear.Sophomore },
                     new Student { 
                         FirstName = "Yan", 
                         LastName = "Li", 
                         Year = AcademicYear.Junior },
                     new Student { 
                         FirstName = "Peggy", 
                         LastName = "Justice", 
                         Year = AcademicYear.Junior },
                     new Student { 
                         FirstName = "Laura", 
                         LastName = "Norman", 
                         Year = AcademicYear.Senior },
                     new Student { 
                         FirstName = "Nino", 
                         LastName = "Olivetto", 
                         Year = AcademicYear.Senior }
                     );
    
                context.SaveChanges();
    
                context.Courses.AddOrUpdate(
                    new Course { Title = "Chemistry", Credits = 3 },
                    new Course { Title = "Microeconomics", Credits = 3 },
                    new Course { Title = "Macroeconomics", Credits = 3 },
                    new Course { Title = "Calculus", Credits = 4 },
                    new Course { Title = "Trigonometry", Credits = 4 },
                    new Course { Title = "Composition", Credits = 3 },
                    new Course { Title = "Literature", Credits = 4 }
                    );
    
                context.SaveChanges();
    
                context.Enrollments.AddOrUpdate(
                    new Enrollment { StudentID = 1, CourseID = 1, Grade = 1 },
                    new Enrollment { StudentID = 1, CourseID = 2, Grade = 3 },
                    new Enrollment { StudentID = 1, CourseID = 3, Grade = 1 },
                    new Enrollment { StudentID = 2, CourseID = 4, Grade = 2 },
                    new Enrollment { StudentID = 2, CourseID = 5, Grade = 4 },
                    new Enrollment { StudentID = 2, CourseID = 6, Grade = 4 },
                    new Enrollment { StudentID = 3, CourseID = 1 },
                    new Enrollment { StudentID = 4, CourseID = 1 },
                    new Enrollment { StudentID = 4, CourseID = 2, Grade = 4 },
                    new Enrollment { StudentID = 5, CourseID = 3, Grade = 3 },
                    new Enrollment { StudentID = 6, CourseID = 4 },
                    new Enrollment { StudentID = 7, CourseID = 5, Grade = 2 }
                    );
    
                context.SaveChanges();
            }
        }
    }
    
  3. Guardar Configuration.cs.

  4. En la consola del Administrador de paquetes, ejecute el comando add-migration initial.

  5. Ejecute el comando update-database.

    Si recibe una excepción al ejecutar este comando, los StudentID valores y CourseID pueden ser diferentes de los valores del Seed método. Abra esas tablas de base de datos y busque los valores existentes para StudentID y CourseID. Agregue esos valores al código para inicializar la Enrollments tabla.

Agregar un control GridView

Con los datos de base de datos rellenados, ya está listo para recuperar esos datos y mostrarlos.

  1. Abra Students.aspx.

  2. Busque el marcador de MainContent posición. Dentro de ese marcador de posición, agregue un control GridView que incluya este código.

    <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
        <asp:GridView runat="server" ID="studentsGrid"
            ItemType="ContosoUniversityModelBinding.Models.Student" DataKeyNames="StudentID" 
            SelectMethod="studentsGrid_GetData"
            AutoGenerateColumns="false">
            <Columns>
                <asp:DynamicField DataField="StudentID" />
                <asp:DynamicField DataField="LastName" />
                <asp:DynamicField DataField="FirstName" />
                <asp:DynamicField DataField="Year" />          
                <asp:TemplateField HeaderText="Total Credits">
                  <ItemTemplate>
                    <asp:Label Text="<%# Item.Enrollments.Sum(en => en.Course.Credits) %>" 
                        runat="server" />
                  </ItemTemplate>
                </asp:TemplateField>        
            </Columns>
        </asp:GridView>
    </asp:Content>
    

    Aspectos a considerar:

    • Observe el valor establecido para la SelectMethod propiedad en el elemento GridView. Este valor especifica el método usado para recuperar los datos de GridView, que se crean en el paso siguiente.

    • La ItemType propiedad se establece en la Student clase creada anteriormente. Esta configuración permite hacer referencia a las propiedades de clase en el marcado. Por ejemplo, la Student clase tiene una colección denominada Enrollments. Puede usar Item.Enrollments para recuperar esa colección y, a continuación, usar la sintaxis LINQ para recuperar la suma de créditos inscritos de cada alumno.

  3. Guarde Students.aspx.

Adición de código para recuperar datos

En el Students.aspx archivo de código subyacente, agregue el método especificado para el SelectMethod valor.

  1. Abra Students.aspx.cs.

  2. Agregue using declaraciones para los espacios de nombres ContosoUniversityModelBinding. Models y System.Data.Entity.

    using ContosoUniversityModelBinding.Models;
    using System.Data.Entity;
    
  3. Agregue el método especificado para SelectMethod:

    public IQueryable<Student> studentsGrid_GetData()
    {
        SchoolContext db = new SchoolContext();
        var query = db.Students.Include(s => s.Enrollments.Select(e => e.Course));
        return query;
    }
    

    La Include cláusula mejora el rendimiento de las consultas, pero no es necesario. Sin la cláusula Include, los datos se recuperan mediante la cargadiferida, lo que implica enviar una consulta independiente a la base de datos cada vez que se recuperan los datos relacionados. Con la cláusula Include, los datos se recuperan mediante la cargadiligente, lo que significa que una consulta de base de datos única recupera todos los datos relacionados. Si no se usan datos relacionados, la carga diligente es menos eficaz porque se recuperan más datos. Sin embargo, en este caso, la carga diligente proporciona el mejor rendimiento porque se muestran los datos relacionados para cada registro.

    Para obtener más información sobre las consideraciones de rendimiento al cargar datos relacionados, consulte la sección Carga diferida, diligente y explícita de datos relacionados en el artículo Leer datos relacionados con Entity Framework en un artículo de aplicación de MVC de ASP.NET.

    De forma predeterminada, los datos se ordenan por los valores de la propiedad marcados como clave. Puede agregar una OrderBy cláusula para especificar un valor de ordenación diferente. En este ejemplo, se usa la propiedad predeterminada StudentID para la ordenación. En el artículo Ordenar, paginar y filtrar datos, el usuario está habilitado para seleccionar una columna para ordenar.

  4. Guarde Students.aspx.cs.

Ejecución de la aplicación

Ejecute la aplicación web (F5) y vaya a la página Estudiantes, que muestra lo siguiente:

show data

Generación automática de métodos de enlace de modelos

Al trabajar con esta serie de tutoriales, simplemente puede copiar el código del tutorial al proyecto. Sin embargo, una desventaja de este enfoque es que es posible que no conozca la característica proporcionada por Visual Studio para generar código automáticamente para los métodos de enlace de modelos. Al trabajar en sus propios proyectos, la generación automática de código puede ahorrar tiempo y ayudarle a obtener una idea de cómo implementar una operación. En esta sección se describe la característica de generación automática de código. Esta sección solo es informativa y no contiene ningún código que necesite implementar en el proyecto.

Al establecer un valor para las propiedades SelectMethod, UpdateMethod, InsertMethod o DeleteMethod en el código de marcado, puede seleccionar la opción Crear nuevo método.

create a method

Visual Studio no solo crea un método en el código subyacente con la firma adecuada, sino que también genera código de implementación para realizar la operación. Si primero establece la propiedad ItemType antes de usar la característica de generación automática de código, el código generado usa ese tipo para las operaciones. Por ejemplo, al establecer la propiedad UpdateMethod, se genera automáticamente el código siguiente:

// The id parameter name should match the DataKeyNames value set on the control
public void studentsGrid_UpdateItem(int id)
{
    ContosoUniversityModelBinding.Models.Student item = null;
    // Load the item here, e.g. item = MyDataLayer.Find(id);
    if (item == null)
    {
        // The item wasn't found
        ModelState.AddModelError("", String.Format("Item with id {0} was not found", id));
        return;
    }
    TryUpdateModel(item);
    if (ModelState.IsValid)
    {
        // Save changes here, e.g. MyDataLayer.SaveChanges();

    }
}

De nuevo, este código no necesita agregarse al proyecto. En el siguiente tutorial, implementará métodos para actualizar, eliminar y agregar nuevos datos.

Resumen

En este tutorial, ha creado clases de modelo de datos y ha generado una base de datos a partir de esas clases. Ha rellenado las tablas de base de datos con datos de prueba. Ha usado el enlace de modelos para recuperar datos de la base de datos y, a continuación, ha mostrado los datos en una clase GridView.

En el siguiente tutorial de esta serie, habilitará la actualización, eliminación y creación de datos.