Ticker

6/recent/ticker-posts

ASP.NET Core - PAGINACIÓN en MVC con C#


Hola que tal, hoy quiero compartirles acerca de  la paginación en ASP.NET Core para este demo estoy considerando el CRUD elaborado en ASP.NET Core - Implementando CRUD en MVC con C#, haré uso de la tabla usuario creado en la base de datos BD_SEGURIDAD.

Requisitos:
Microsoft Visual Studio Community 2019
Microsoft .NET Core, ASP.NET Core
Lenguaje de programación C# y T-SQL  (manipulación de datos)
Microsoft SQL Server 2017 (RTM-GDR) - Express Edition (64-bit)
Framework Bootstrap (para mejorar el diseño de nuestra aplicación)

Crear el procedimiento almacenado:
Crearemos el procedimiento almacenado de (T-SQL) nombre GET_USUARIO en nuestro base de datos BD_SEGURIDAD. 

CREATE PROCEDURE GET_USUARIO
(
       @OffsetValue int,
       @PagingSize int
)
AS
BEGIN
       SELECT Id, Usuario, Contrasena, Intentos, NivelSeg, FechaReg FROM USUARIO ORDER BY Id
       OFFSET @OffsetValue ROWS FETCH NEXT @PagingSize ROWS ONLY;

       Select count(Id) as TotalRows from USUARIO
END

Nos conectamos a SQL desde el IDE de Visual Studio, clic derecho y clic en Agregar nuevo procedimiento almacenado, pegar el script en la sección sql y clic en Actualizar
Verificación de la tabla creada

Lo procedimiento almacenado cuenta con 2 parámetros de entrada, dichos parámetros sirve para poder definir el rango de registros a seleccionar - es decir si defino al parámetro @PagingSize con valor 5 voy a mostrar en tabla o grilla en grupo de 5 registros:

       *SELECT Id, Usuario, Contrasena, Intentos, NivelSeg, FechaReg FROM USUARIO ORDER BY Id
       OFFSET @OffsetValue ROWS FETCH NEXT @PagingSize ROWS ONLY;

*Donde mis parámetros iniciales sería @OffsetValue = 0 y PagingSize = 5

       **Select count(Id) as TotalRows from USUARIO

**Cuento la cantidad de registro existente y retorno en la parámetro TotalRows de tipo de salida.

Agregar key en appsettings.json:
Crearemos un nuevo key de nombre PageZise con el valor 5, es decir nuestro rango de registros a seleccionar será de 5 en 5.

  "KeyConfig": {
    "PageSize": "5"
  }

Recuerde que la cadena de conexión se mantiene en el archivo appsettings.json. 

Para acceder a este archivo (appsettings.json.), se debe obtener el objeto de la interfaz IConfiguration a través de la función Inyección de dependencias. Por lo tanto, se agrega la interfaz IConfiguration en el constructor de HomeController y el patrón del MVC que nos proporcionará automáticamente el objeto.

Agregar IActionResult paginado:
Ahora crearemos la funcionalidad de paginado, para cual agregaremos 2 nuevos IActionResult. Por lo tanto, agregue los IActionResult de  la acción Create al Home Controller como se muestra a continuación:

La explicación del código en los comentarios del código

        public IActionResult Usuario() {
            return View();
        }

        [HttpGet]
        [ActionName("Usuario")]
        public IActionResult UsuarioPage(int page = 1)
        {
            //capturamos el valor PageSize, esta definido como 5
            int PageSize = Convert.ToInt16(Configuration["KeyConfig:PageSize"]);
            //creamos el objeto ViewModel
            UsuarioViewModel _usuarioViewModel = new UsuarioViewModel();
            DataSet ds = new DataSet();
            //listamos los campos de usuario
            List<ClsUsuario> ListclsUsuarios = new List<ClsUsuario>();

            //Conexión a la base de datos
            string connectionString = Configuration["ConnectionStrings:DefaultConnection"];
            //Estoy usando uso de ADO.Net para interactuar con la base de datos, puede usar cualquier otros ORM
            using (SqlConnection connection = new SqlConnection(connectionString))
            //using (SqlConnection con = new SqlConnection(Configuration["ConnectionStrings:DefaultConnection"]))
            {
                connection.Open();
                SqlCommand com = new SqlCommand("GET_USUARIO", connection);
                com.CommandType = CommandType.StoredProcedure;
                //Paso los parametros para seleccionar el rango
                com.Parameters.AddWithValue("@OffsetValue", (page - 1) * PageSize);
                com.Parameters.AddWithValue("@PagingSize", PageSize);
                SqlDataAdapter adapt = new SqlDataAdapter(com);
                //Cargo el conjunto de datos con fill y cierro la conexión a base de datos
                adapt.Fill(ds);
                connection.Close();
                //Ahora asocio los datos de usuario
                //Estamos retornando 2 conjunto de datos, una contiene los datos del usuario y otra contiene la cantidad total de registros existente en la tabla usuario
                if (ds != null && ds.Tables.Count == 2)
                {
                    for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                    {
                        ClsUsuario clsUsuario = new ClsUsuario();
                        clsUsuario.id = Convert.IsDBNull(ds.Tables[0].Rows[i]["Id"]) ? 0 : Convert.ToInt32(ds.Tables[0].Rows[i]["Id"]);
                        clsUsuario.usuario = Convert.IsDBNull(ds.Tables[0].Rows[i]["Usuario"]) ? "" : Convert.ToString(ds.Tables[0].Rows[i]["Usuario"]);
                        clsUsuario.contrasena = Convert.IsDBNull(ds.Tables[0].Rows[i]["Contrasena"]) ? "" : Convert.ToString(ds.Tables[0].Rows[i]["Contrasena"]);
                        clsUsuario.intentos = Convert.IsDBNull(ds.Tables[0].Rows[i]["Intentos"]) ? 0 : Convert.ToInt32(ds.Tables[0].Rows[i]["Intentos"]);
                        clsUsuario.nivelSeg = Convert.IsDBNull(ds.Tables[0].Rows[i]["NivelSeg"]) ? 0 : Convert.ToDecimal(ds.Tables[0].Rows[i]["NivelSeg"]);
                        clsUsuario.fechaReg = Convert.IsDBNull(ds.Tables[0].Rows[i]["FechaReg"]) ? (DateTime?)null : Convert.ToDateTime(ds.Tables[0].Rows[i]["FechaReg"]);
                        ListclsUsuarios.Add(clsUsuario);
                    }
                    //Pasamos el total de registros para la página actual
                    var pager = new Pager((ds.Tables[1] != null && ds.Tables[1].Rows.Count > 0) ? Convert.ToInt32(ds.Tables[1].Rows[0]["TotalRows"]) : 0, page, PageSize);
                    _usuarioViewModel.ListUsuario = ListclsUsuarios;
                    _usuarioViewModel.pager = pager;
                }
            }
            return View(_usuarioViewModel);

        }

Agregar Views paginado:
A continuación, cree una nuevo view llamada Usuario.cshtml dentro de esta carpeta Home (es decir, Views/Home) y agregue el siguiente código a esta Vista:

@model DEMO01_CRUD.Models.UsuarioViewModel
@{
    var title = "PAGINACION CON ADO.NET";
    ViewData["Title"] = title;
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="row justify-content-center">
    <h4>@title</h4>
</div>

<p>
    <a asp-action="Create">Create New</a>
</p>
<div class="container">
    <table class="table table-bordered">
        <thead>
            <tr>
                <th>Id</th>
                <th>Usuario</th>
                <th>Contraseña</th>
                <th>Intentos</th>
                <th>Nivel Seguridad</th>
                <th>Fecha Registro</th>
                @*<th>Botones</th>*@
            </tr>
        </thead>
        <tbody>
            @if (Model.ListUsuario != null)
            {
                for (int i = 0; i < Model.ListUsuario.Count; i++)
                {
            <tr>
                <td>@Model.ListUsuario[i].id</td>
                <td>@Model.ListUsuario[i].usuario</td>
                <td>@Model.ListUsuario[i].contrasena</td>
                <td>@Model.ListUsuario[i].intentos</td>
                <td>@Model.ListUsuario[i].nivelSeg</td>
                <td>@string.Format("{0:dd/MM/yyyy}", @Model.ListUsuario[i].fechaReg)</td>
                @*<td>@string.Format("{0:dddd, dd MMMM yyyy}", @Model.ListUsuario[i].fechaReg)</td>*@
                <td>
                    @Html.ActionLink("Edit", "Edit", new { id = @Model.ListUsuario[i].id }) |
                    @Html.ActionLink("Details", "Details", new { id = @Model.ListUsuario[i].id }) |
                    @Html.ActionLink("Delete", "Delete", new { id = @Model.ListUsuario[i].id })
                </td>
            </tr>
                }
            }
        </tbody>
    </table>

    <div class="row justify-content-center">
        <!-- paginación -->
        @if (Model.pager.EndPage > 1)
        {
        <ul class="pagination">

            @if (Model.pager.CurrentPage > 1)
            {
                <li>
                    <a href="~/Home/Usuario">Primero</a>
                </li>
                <li>
                    <a href="~/Home/Usuario?page=@(Model.pager.CurrentPage - 1)">Anterior</a>
                </li>
            }
            else if (Model.pager.CurrentPage == 1)
            {
                <li>
                    <a href="~/Home/Usuario">Primero</a>
                </li>
            }

            <!--Paginación activa-->
            @for (var p = Model.pager.StartPage; p <= Model.pager.EndPage; p++)
            {
                <li class="@(p == Model.pager.CurrentPage ? "active" : "")">
                    <a href="~/Home/Usuario?page=@p">@p</a>
                </li>
            }

            @if (Model.pager.CurrentPage < Model.pager.TotalPages)
            {
                <li>
                    <a href="~/Home/Usuario?page=@(Model.pager.CurrentPage + 1)">Siguiente</a>
                </li>
                <li>
                    <a href="~/Home/Usuario?page=@(Model.pager.TotalPages)">Último</a>
                </li>
            }
            else if (Model.pager.CurrentPage == Model.pager.TotalPages)
            {
                <li>
                    <a href="~/Home/Usuario?page=@(Model.pager.TotalPages)">Último</a>
                </li>
            }
        </ul>
        }
    </div>

Modificar enrutamiento de action:
Ahora cambiemos el enrutamiento de  action a usuario, para lo cual ingresa a la clase Startup.cs:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseStaticFiles();//facilita el uso de los archivos de web root ( wwwroot por defecto)
            app.UseDeveloperExceptionPage();//captura las instancias de excepción y genera respuesta de error
            app.UseMvc(router =>
            {
                router.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Usuario}/{id?}");
            });
        }

Ejecutar la implementación:
Para finalizar ejecutamos la implementación, en el navegador carga los 5 primeros registro. Puedes seguir agregando datos y ver la funcionalidad completa de lo implementado.

Inicialmente cargaremos 5 registros, clic en Siguiente
Cargaremos el paginado 2

Conclusión:
La paginacion en sitios web es la forma de estructurar y agrupar el contenido, agrupándolo por una cantidad fija de espacio o cantidad de elementos. Hay muchas formar de implementarlas, pero el resultado siempre será los mismo - en nuestro caso nos apoyamos en ADO.Net bajo la tecnología de ASP.Net Core y el resultado de la paginación es simplemente el número de páginas que se muestran en la parte inferior de la tabla de resultados que sirve para separar y distribuir el contenido y facilitar la navegación.

Descarga la fuente desde:

Descargar fuente de ASP.NET-Core-CRUD-MVC
Agradecer de antemano por la revisión y lectura de este artículo, nos vemos en el siguiente artículo.

Publicar un comentario

2 Comentarios

  1. Hola como estas, me puedes dar clases de .Net ?

    ResponderBorrar
    Respuestas
    1. Hola, con quien tengo el gusto - me puedes escribir a hadson1@gmail o por el chat del fan page https://www.facebook.com/hadsonpar

      Borrar