Ir al contenido principal

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 Framework
Microsoft SQL Server 2017 (RTM-GDR) - Express Edition (64-bit)
Framework Bootstrap (para mejorar el diseño de nuestra aplicación)
Framework  jQuery Validation (para la validación de lado del cliente)

Crear el procedimiento almacenado:
Crearemos el procedimiento almacenado de 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.

Pronto podrás descargar la fuente desde:
 Descargar fuente de ASP.NET-Core-CRUD-MVC
Agradecer de antemano por la revisión y lectura de este pequeño apartado, nos vemos en el siguiente tutorial.

Comentarios

Entradas más populares de este blog

Habilitar Usuario HR Oracle

Al realizar la primera instalación del Oracle, el usuario HR por defecto está bloqueado y por ende no podemos loguearnos como dicho usuario, lo que debe hacer son los siguiente pasos, aplicables para Linux o Windows.
1. Conectarse como usuario system o sysdba + contraseña haciendo uso del comando connect.
Usuario: system
Password: xxxx 


2. Hacer uso  del comando alter user hr account unlock desbloqueamos la cuenta.
alter user hr account unlock;

3. Escribimos el comando alter user HR identified by hr; con esto estamos diciendo que la contraseña será hr.

alter user HR identified by hr;

4. Ahora testeamos la conexión con el comando - conn hr/hr@xe. Si deseas después de conectarnos se puede realizar un select a la tabla employees del hr.


Resultado del select realizado
5. Con todos estos pasos realizados ya podemos logearnos desde cualquier IDE como el usuario hr  y la contraseña hr que definimos en el paso 3. 
Para finalizar nos loguearemos con el IDE Oracle SQL Developer.

Espero les sea de utilidad,…

Usuario SYS y SYSTEM - ORACLE

Usuario SYS y SYSTEM
Ambos usuario son creados de forma automática al crear la base de datos ORACLE y se otorga el rol de DBA.

SYS (password por defecto: CHANGE_ON_INSTALL).
SYSTEM (password por defecto: MANAGER).

Lo que se recomienda es cambiar el password de ambos usuarios por el tema de seguridad.

SYS:
Todas las tablas y vistas para el diccionario de datos de la base de datos están almacenados en el esquema SYS. Estas tablas y vistas son críticas para el funcionamiento de la base de datos ORACLE. Para mantener la integridad del diccionario de datos, las tablas del esquema SYS son manipulados solo por la base de datos. Nunca se debería modificar algo o crear tablas en el esquema del usuario SYS.

SYSTEM:
El usuario SYSTEM se utiliza para crear tablas y vistas adicionales que muestran información administrativa, tablas internas y vistas utilizado por varias opciones y herramientas de la base de datos ORACLE. No se recomienda utilizar el esquema SYSTEM para almacenar tablas de interés para usu…

Parámetro de entrada y salida – PL/SQL

Parámetro de entrada y salida – PL/SQL:
Los parámetros de entrada y salida no son los parámetros de inicialización de la base de datos ORACLE. Los parámetros de entra y salida son utilizados mayormente en implementaciones de funciones, procedimientos almacenados o bloques de código bajo el lenguaje del PL/SQL, se considera que ambos parámetros (entra y salida) puedan realizar operaciones en el mismo bloque PL/SQL, es decir, si enviamos un parámetro de entrada hará que cumpla cierta operación y retornara los valores de salida de dicha operación procesada de acuerdo al parámetro de ingresado. Es de acuerdo al caso que nos presenta en la implementación.
Algo importante al definir los parámetros, es saber y considerar cuántos tipos de parámetro existe si solo hablamos de entrada y salida, en realidad mi determinación seria 3 tipos:

Parámetros:

IN – entrada
OUT – salida
IN OUT – entrada salida

Parámetro IN – entrada:
El comportamiento común de estés tipos de parámetros es estar siempre pendiente d…