Mostrando las entradas con la etiqueta Controlador. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Controlador. Mostrar todas las entradas

lunes, 25 de enero de 2016

Videos Curso ASP.NET MVC & JavaScript HTE (Parte 1)

Videos del Curso ASP.NET MVC & JavaScript HTE (Parte 1)

Comparto la primera parte del curso de ASP.NET MVC & JavaScript realizado en la Empresa HTE donde todo se trabaja en forma desconectada usando en el Servidor mi Serializador de Cadenas y JavaScript en el Cliente, sobre todo Matrices.

1. Curso MVC & JavaScript HTE - Demo 01

En este video se muestra como crear una simple aplicación web usando un Formulario Web y Controles Web.

El ejemplo muestra una consulta de empleados, se ingresa el código y se envía la consulta al servidor obteniendo los datos de este y mostrando un mensaje por JavaScript.

Además permite crear un archivo de texto con los datos del empleado y bajarlo al cliente.


2. Curso MVC & JavaScript HTE - Demo 02

En este video se muestra como crear una simple aplicación web con ASP.NET MVC, sobre todo se muestra como pasar datos desde el cliente al servidor usando parámetros el método de acción.

También se muestra como enviar datos desde el servidor al cliente  de diferentes formas, entre ellas usando ViewData y usando un Modelo.


3. Curso MVC & JavaScript HTE - Demo 03

En este video se muestran los diferentes Tipos de Resultados de Acciones en MVC, tales como ActionResult, ContentResult (string y DateTime), JsonResult, FileResult y JavaScriptResult.


4. Curso MVC & JavaScript HTE - Demo 04

En este video se muestra como crear una Consulta Asíncrona usando XmlHttpRequest (XHR) enviando Cadenas (String) mediante un serializador personalizado y creando una tabla en JavaScript.

Para el ejemplo se trabaja con una lista de clientes: código, nombre, dirección y contacto.


5. Curso MVC & JavaScript HTE - Demo 05

En este video se muestra como crear un filtro desconectado usando cadenas y matrices. El filtro se hace mediante un control textbox y los resultados se muestran en una tabla.

El ejemplo es con la tabla Clientes de Northwind, se consulta por nombre y se se muestran el código, nombre, dirección y contacto.


6. Curso MVC & JavaScript HTE - Demo 06 (Parte 1)

En este video se muestra la primera parte de como crear un filtro desconectado mediante un ComboBox y usando Cadenas y Matrices en JavaScript.

Para el ejemplo se muestra en un ComboBox las Categorías y al seleccionar una se muestran los Productos por Categoría, pero todo es en el lado del cliente usando JavaScript.


7. Curso MVC & JavaScript HTE - Demo 06 (Parte 2)

En este video se muestra la segunda parte de como crear un filtro desconectado mediante un ComboBox y usando Cadenas y Matrices en JavaScript.

Para el ejemplo se muestra en un ComboBox las Categorías y al seleccionar una se muestran los Productos por Categoría, pero todo es en el lado del cliente usando JavaScript.


8. Curso MVC & JavaScript HTE - Demo 07

En este video se enseña como crear un filtro desconectado mediante las cabeceras de la tabla usando controles de texto para filtrar cada campo.

El ejemplo es con la tabla productos y se puede filtrar por código, nombre, proveedor, categoría, precio y stock mediante JavaScript.


9. Curso MVC & JavaScript HTE - Demo 08

En este video se enseña como crear un filtro desconectado mediante las cabeceras de la tabla usando controles de textos y combos para filtrar cada campo.

El ejemplo es con la tabla productos y se puede filtrar por código, nombre, proveedor, categoría, precio y stock mediante JavaScript.


martes, 22 de diciembre de 2015

El Demo del Día: Aplicación de Simple Página (SPA) en ASP.NET MVC

Aplicación de Simple Página (SPA) en ASP.NET MVC

Después de mucho tiempo vamos a presentar un nuevo Demo, esta vez comparando una Aplicación de Múltiples Páginas (MPA) con una Aplicación de Simple Página (SPA), pero sin usar ningún Framework SPA como AngularJS, Knockout, Ember, Meteor, Kendo UI, etc.

Introducción a una SPA

El modelo por defecto en ASP.NET sea WebForms o MVC es MPA, quiere decir que nuestro sitio web se compone de varias páginas las cuales se solicitan desde el cliente una a una y cada una descarga sus archivos necesarios: HTML, JavaScript, CSS, Imágenes, Fuentes, etc.
En cambio si nuestro sitio solo tuviera una simple página solo se cargaría una sola vez todos los archivos.

Ventajas de una SPA

La gran ventaja de una Aplicación de Simple Página (SPA) es que evita conectarse varias veces al servidor para solicitar cada página, es decir, favorece el trabajo desconectado, ya que al haber una sola página se pueda cargar todos los datos necesarios al inicio, así como los JavaScripts y las hojas de estilo.

Trabajar con una sola página ayuda a la Performance, ya que evita conexiones innecesarias al servidor web.

Usos de una SPA

Generalmente, los sitios web móviles usan este modelo, ya que solo se carga una página y se va presentando secciones (llamadas cartas o barajas) de ésta, muchos de los Frameworks para Aplicaciones Web Móviles trabajan de esta forma, por ejemplo jQuery Mobile, Bootstrap, etc.

Pero si nuestra Aplicación Web no tiene demasiadas páginas ni datos que cargar, también podemos usar este modelo, ahorrando conexiones al servidor, es decir, trabajando en forma desconectada.

Características de una SPA

Existen muchas características de una SPA:
- La principal es que la aplicación solo tenga una página.
- Aunque no es exclusividad de una SPA, actualmente el Diseño Web debe ser Adaptativo (Responsive Web Design).
- Otra característica importante (que también no es exclusividad de SPA) es que debe hacer llamadas Asíncronas JavaScript HTTP: AJAX (Xml), AJAJ (JSON) o AJAS (Strings).

Ejemplo de Comparación entre MPA y SPA en ASP.NET MVC

A continuación vamos a presentar un ejemplo donde comparamos una Aplicación sobre Pedidos que tiene los 2 modelos:

- MPA: Compuesto por un Controlador llamado MPA que tiene 4 métodos de acción y 4 vistas, llamadas Login, Categoria, Producto y Pedido. La navegación entre cada una implica ir al servidor y esperar su respuesta, para lo cual a propósito se ha puesto un tiempo de espera. Este modelo usa 4 archivos de JavaScript, uno para cada página.

- SPA: Compuesto por un Controlador llamado SPA que tiene solo un método de acción y una vista llamada Pedido. Por otra parte solo hay un archivo de JavaScript llamado Todo.js que realiza la navegación entre páginas (divs) y que no viaja al servidor sino solo se hace en el cliente.

Crear una Aplicación ASP.NET MVC 4 en C#

- Abrir Visual Studio 2012 y crear un proyecto de tipo "Aplicación web de ASP.NET MVC4" y asignarle como nombre: "SinglePageApplication".

- Seleccionar la opción "Vacio" y como motor de vista "Razor" y "Aceptar".

Crear el Controlador MPA

- Clic derecho a la carpeta Controllers y seleccionar "Agregar" y luego "Controlador".

- Ingresar como nombre "MPAController" y luego escribir el siguiente código:

using System;
using System.Web;
using System.Web.Mvc;

namespace SinglePageApplication.Controllers
{
    public class MPAController : Controller
    {
        public ActionResult Login()
        {
            return View();
        }

        public ActionResult Categoria()
        {
            //Simular que esta conectandose a la BD para traer las Categorias
            System.Threading.Thread.Sleep(2000);
            return View();
        }

        public ActionResult Producto()
        {
            //Simular que esta conectandose a la BD para traer los Productos x Categoria
            System.Threading.Thread.Sleep(4000);
            return View();
        }

        public ActionResult Pedido()
        {
            //Simular que esta leyendo del TempData los Pedidos
            System.Threading.Thread.Sleep(1000);
            return View();
        }
    }
}

Crear una Hoja de Estilo para todas las vistas

- Crear una carpeta para los archivos CSS llamado: "Estilos".

- Crear una hoja de estilo llamada "ACME.css" dentro de la carpeta Estilos y escribir el siguiente código:

body {
    background-color:aqua;
    width:100%;
}
.Titulo {
    background-color:blue;
    color:white;
    font-family:Arial;
    font-size:xx-large;
    text-align:center;  
}
.Subtitulo {
    background-color:white;
    color:blue;
    font-family:Arial;
    font-size:x-large;
    text-align:center;
}
table {
    width:100%;
}
.FilaCabecera {
    background-color:lightgray;
    color:black;
}
.FilaDatos {
    background-color:white;
    color:black;
}
.Pagina {
    display:none;
}

Crear las Vistas para MPA

- Ir al controlador MPA, clic derecho sobre el nombre del método "Login" y crear una vista con el mismo nombre que tenga el siguiente código HTML:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Login</title>
    <link href="~/Estilos/ACME.css" rel="stylesheet" />
</head>
<body>
    <div id="divLogin">
        <div id="divCabeceraLogin">
            <div id="divTituloLogin" class="Titulo">
                <span id="spnTitulo">Aplicación de Múltiples Paginas (MPA)</span>
            </div>
            <div id="divSubtituloLogin" class="Subtitulo">
                <span id="spnSubtituloLogin">Login del Sistema</span>
            </div>
        </div>
        <div id="divCuerpoLogin">
            <div id="divEtiquetaUsuario">
                <span id="spnUsuario">Usuario: </span>
            </div>
            <div id="divTextoUsuario">
                <input id="txtUsuario" type="text" />
            </div>
            <div id="divEtiquetaClave">
                <span id="spnClave">Clave: </span>
            </div>
            <div id="divTextoClave">
                <input id="txtClave" type="password" />
            </div>
            <div id="divBotonesLogin">
                <input id="btnAceptar" type="button" value="Aceptar" />
            </div>
        </div>
        <div id="divPieLogin">
            <div id="divUbicacion" class="Subtitulo">
                <span id="spnUbicacion">Lima - Perú</span>
            </div>
        </div>
    </div>
    <script src="~/Scripts/Login.js"></script>
</body>
</html>

- Ir al controlador MPA, clic derecho sobre el nombre del método "Categoria" y crear una vista con el mismo nombre que tenga el siguiente código HTML:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Categoria</title>
    <link href="~/Estilos/ACME.css" rel="stylesheet" />
</head>
<body>
    <div id="divCategoria">
        <div id="divCabeceraCategoria">
            <div id="divSubtituloCategoria" class="Subtitulo">
                <span id="spnSubtituloCategoria">Selecciona una Categoria</span>
            </div>
        </div>
        <div id="divListaCategoria">
            <span id="spnListaCategoria">Aqui se debe mostrar un lista de Categorias</span>
        </div>
        <div id="divPieCategoria">
            <div id="divNavegarCategoria" class="Subtitulo">
                <a id="aCatProd" href="~/MPA/Producto">Productos</a>
            </div>
        </div>
    </div>
    <script src="~/Scripts/Categoria.js"></script>
</body>
</html>

- Ir al controlador MPA, clic derecho sobre el nombre del método "Producto" y crear una vista con el mismo nombre que tenga el siguiente código HTML:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Producto</title>
    <link href="~/Estilos/ACME.css" rel="stylesheet" />
</head>
<body>
    <div id="divProducto">
        <div id="divCabeceraProducto">
            <div id="divSubtituloProducto" class="Subtitulo">
                <span id="spnSubtituloProducto">Agrega Productos a tu Pedido</span>
            </div>
        </div>
        <div id="divListaProducto">
            <span id="spnListaProducto">Aqui se debe mostrar un lista de Productos</span>
        </div>
        <div id="divPieProducto">
            <div id="divNavegarProducto" class="Subtitulo">
                <a id="aProdPed" href="~/MPA/Pedido">Pedidos</a>
                <a id="aProdCat" href="~/MPA/Categoria">Regresar</a>
            </div>
        </div>
    </div>
    <script src="~/Scripts/Producto.js"></script>
</body>
</html>

- Ir al controlador MPA, clic derecho sobre el nombre del método "Pedido" y crear una vista con el mismo nombre que tenga el siguiente código HTML:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Pedido</title>
    <link href="~/Estilos/ACME.css" rel="stylesheet" />
</head>
<body>
    <div id="divPedido">
        <div id="divCabeceraPedido">
            <div id="divSubtituloPedido" class="Subtitulo">
                <span id="spnSubtituloPedido">Agrega Productos a tu Pedido</span>
            </div>
        </div>
        <div id="divListaPedido">
            <span id="spnListaPedido">Aqui se debe mostrar un lista de Pedidos</span>
        </div>
        <div id="divPiePedido">
            <div id="divNavegarPedido" class="Subtitulo">
                <a id="aPedCat" href="~/MPA/Categoria">Regresar</a>
            </div>
        </div>
    </div>
    <script src="~/Scripts/Pedido.js"></script>
</body>
</html>

Crear los JavaSripts para MPA

- Crear una carpeta para los archivos js llamado: "Scripts"

- Crear una archivo de JavaScript llamado "Login.js" dentro de la carpeta Scripts y escribir el siguiente código:

window.onload = function () {
    var btnAceptar = document.getElementById("btnAceptar");
    btnAceptar.onclick = function () {
        var txtUsuario = document.getElementById("txtUsuario");      
        if (txtUsuario.value == "") {
            alert("Ingresa el Usuario");
            txtUsuario.focus();
            return false;
        }
        var txtClave = document.getElementById("txtClave");
        if (txtClave.value == "") {
            alert("Ingresa la Clave");
            txtClave.focus();
            return false;
        }
        if (txtUsuario.value == "Luis" && txtClave.value == "123") {
            window.location.href = "MPA/Categoria";
        }
        else {
            alert("Login invalido");
        }
    }
}

- Crear una archivo de JavaScript llamado "Categoria.js" dentro de la carpeta Scripts y escribir el siguiente código:

window.onload = function () {
    alert("Cargando Categorias");
}

- Crear una archivo de JavaScript llamado "Producto.js" dentro de la carpeta Scripts y escribir el siguiente código:

window.onload = function () {
    alert("Cargando Productos");
}

- Crear una archivo de JavaScript llamado "Pedido.js" dentro de la carpeta Scripts y escribir el siguiente código:

window.onload = function () {
    alert("Cargando Pedidos");
}

Configurar el Inicio del MPA

- Ir a la carpeta "App_Start" y abrir el archivo "RouteConfig.css" y cambiar el nombre del controlador y la acción que inicia.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace SinglePageApplication
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "MPA", action = "Login", id = UrlParameter.Optional }
            );
        }
    }
}

Probar y Ejecutar la Aplicación de Múltiples Páginas (MPA)

- Grabar y ejecutar la aplicación pulsando F5 y se mostrará una ventana similar a la siguiente figura:


- Ingresar como usuario "Luis" y como clave "123" y "Aceptar", observando que se demora en cargar la segunda página de Categoria, similar a la siguiente figura:


- Clic al enlace de Productos y después de esperar un momento se mostrará la página de Producto, similar a la siguiente figura:


- Clic al enlace de Pedidos y después de esperar un momento se mostrará la página de Pedido, similar a la siguiente figura:


- Si deseas en cualquier página puedes seleccionar el enlace "Regresar".

Nota: En todos los enlaces al dar clic se irá al servidor para cargar la página ya que el modelo es MPA.

Crear el Controlador SPA

- Clic derecho a la carpeta Controllers y seleccionar "Agregar" y luego "Controlador".

- Ingresar como nombre "SPAController" y luego escribir el siguiente código:

using System;
using System.Web;
using System.Web.Mvc;

namespace SinglePageApplication.Controllers
{
    public class SPAController : Controller
    {
        public ActionResult Pedido()
        {
            return View();
        }
    }
}

Crear la Vista para SPA

- Ir al controlador SPA, clic derecho sobre el nombre del método "Pedido" y crear una vista con el mismo nombre que tenga el siguiente código HTML:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Pedido</title>
    <link href="~/Estilos/ACME.css" rel="stylesheet" />
</head>
<body>
    <div id="divTodo">
        <div id="divLogin" class="Pagina">
            <div id="divCabeceraLogin">
                <div id="divTituloLogin" class="Titulo">
                    <span id="spnTitulo">Aplicación de Simple Pagina (SPA)</span>
                </div>
                <div id="divSubtituloLogin" class="Subtitulo">
                    <span id="spnSubtituloLogin">Login del Sistema</span>
                </div>
            </div>
            <div id="divCuerpoLogin">
                <div id="divEtiquetaUsuario">
                    <span id="spnUsuario">Usuario: </span>
                </div>
                <div id="divTextoUsuario">
                    <input id="txtUsuario" type="text" />
                </div>
                <div id="divEtiquetaClave">
                    <span id="spnClave">Clave: </span>
                </div>
                <div id="divTextoClave">
                    <input id="txtClave" type="password" />
                </div>
                <div id="divBotonesLogin">
                    <input id="btnAceptar" type="button" value="Aceptar" />
                </div>
            </div>
            <div id="divPieLogin">
                <div id="divUbicacion" class="Subtitulo">
                    <span id="spnUbicacion">Lima - Perú</span>
                </div>
            </div>
        </div>
        <div id="divCategoria" class="Pagina">
            <div id="divCabeceraCategoria">
                <div id="divSubtituloCategoria" class="Subtitulo">
                    <span id="spnSubtituloCategoria">Selecciona una Categoria</span>
                </div>
            </div>
            <div id="divListaCategoria">
                <span id="spnListaCategoria">Aqui se debe mostrar un lista de Categorias</span>
            </div>
            <div id="divPieCategoria">
                <div id="divNavegarCategoria" class="Subtitulo">
                    <a id="aCatProd" href="#" data-url="divProducto">Productos</a>
                </div>
            </div>
        </div>
        <div id="divProducto" class="Pagina">
            <div id="divCabeceraProducto">
                <div id="divSubtituloProducto" class="Subtitulo">
                    <span id="spnSubtituloProducto">Agrega Productos a tu Pedido</span>
                </div>
            </div>
            <div id="divListaProducto">
                <span id="spnListaProducto">Aqui se debe mostrar un lista de Productos</span>
            </div>
            <div id="divPieProducto">
                <div id="divNavegarProducto" class="Subtitulo">
                    <a id="aProdPed" href="#" data-url="divPedido">Pedidos</a>
                    <a id="aProdCat" href="#" data-url="divCategoria">Regresar</a>
                </div>
            </div>
        </div>
        <div id="divPedido" class="Pagina">
            <div id="divCabeceraPedido">
                <div id="divSubtituloPedido" class="Subtitulo">
                    <span id="spnSubtituloPedido">Agrega Productos a tu Pedido</span>
                </div>
            </div>
            <div id="divListaPedido">
                <span id="spnListaPedido">Aqui se debe mostrar un lista de Pedidos</span>
            </div>
            <div id="divPiePedido">
                <div id="divNavegarPedido" class="Subtitulo">
                    <a id="aPedCat" href="#" data-url="divCategoria">Regresar</a>
                </div>
            </div>
        </div>
    </div>
    <script src="~/Scripts/Todo.js"></script>
</body>
</html>

Crear el JavaSript para SPA

- Crear una archivo de JavaScript llamado "Todo.js" dentro de la carpeta Scripts y escribir el siguiente código:

window.onload = function () {
    //Mostrar la primera pagina
    var divLogin = document.getElementById("divLogin");
    if (divLogin) {
        divLogin.style.display = "inline";
        scriptLogin();
    }
    //Programar toda la navegación
    var enlaces = document.getElementsByTagName("a");
    if (enlaces != null && enlaces.length > 0) {
        var n = enlaces.length;
        var enlace;
        var pagina;
        var script;
        for (var i = 0; i < n; i++) {
            enlace = enlaces[i];
            enlace.onclick = function () {
                ocultarPaginas();
                var id = this.getAttribute("data-url");
                pagina = document.getElementById(id);
                if (pagina != null) {
                    pagina.style.display = "inline";
                    script = id.replace("div", "script");
                    window[script]();
                }
            }
        }
    }
}

function ocultarPaginas() {
    var paginas = document.getElementsByClassName("Pagina");
    if (paginas != null && paginas.length > 0) {
        var n = paginas.length;
        var pagina;
        for (var i = 0; i < n; i++) {
            pagina = paginas[i];
            pagina.style.display = "none";
        }
    }
}

function scriptLogin() {
    var btnAceptar = document.getElementById("btnAceptar");
    btnAceptar.onclick = function () {
        var txtUsuario = document.getElementById("txtUsuario");
        if (txtUsuario.value == "") {
            alert("Ingresa el Usuario");
            txtUsuario.focus();
            return false;
        }
        var txtClave = document.getElementById("txtClave");
        if (txtClave.value == "") {
            alert("Ingresa la Clave");
            txtClave.focus();
            return false;
        }
        if (txtUsuario.value == "Luis" && txtClave.value == "123") {
            var divCategoria = document.getElementById("divCategoria");
            if (divCategoria) {
                ocultarPaginas();
                divCategoria.style.display = "inline";
                scriptCategoria();
            }
        }
        else {
            alert("Login invalido");
        }
    }
}

function scriptCategoria() {
    alert("Cargando Categorias");
}

function scriptProducto() {
    alert("Cargando Productos");
}

function scriptPedido() {
    alert("Cargando Pedidos");
}

Nota: En el evento load de la ventana se muestra solo el primer div (Login) y el resto esta oculto por el estilo de la clase Pagina. Además se obtiene todos los enlaces y se programa para que se navegue al div que especifique el atributo "data-url" ejecutando su script asociado que debe tener el prefijo script seguido del nombre usando: window[script]().

Configurar el Inicio del SPA

- Ir a la carpeta "App_Start" y abrir el archivo "RouteConfig.css" y cambiar el nombre del controlador y la acción que inicia.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace SinglePageApplication
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "SPA", action = "Pedido", id = UrlParameter.Optional }
            );
        }
    }
}

Probar y Ejecutar la Aplicación de Simple Página (SPA)

- Grabar y ejecutar la aplicación pulsando F5 y se mostrará una ventana similar a la siguiente figura:


- Ingresar como usuario "Luis" y como clave "123" y "Aceptar", observando que no se demora en cargar nada la segunda página de Categoria ya que es un div, similar a la siguiente figura:


- Clic al enlace de Productos e inmediatamente se mostrará la página de Producto ya que es un div, similar a la siguiente figura:


- Clic al enlace de Pedidos y e inmediatamente se mostrará la página de Pedido que también es un div, similar a la siguiente figura:


- Si deseas en cualquier página puedes seleccionar el enlace "Regresar"y navegará a la sección especificada.

Nota: En todos los enlaces al dar clic se ocultarán todos los divs y se mostrará uno solo ya que el modelo es SPA, es decir, no se va al servidor sino solo se muestra en el cliente.

Comentario Final

En este post un poco largo hemos querido mostrar como se puede crear sin ningún Framework de JavaScript una Aplicación de Simple Pagina (SPA) tan solo usando divs y un poco de JavaScript, lo cual es muy útil para trabajar en forma desconectada en aplicaciones pequeñas, por ejemplo, las aplicaciones web móviles.

Las personas que desean crear una SPA en MVC usando Frameworks, encontrarán muchos Blogs y Sitios Web, ya que para esto existe mucha información, tanto oficial como no oficial, por ejemplo les alcanzo un enlace del MSDN:
ASP.NET MVC 5: A .NET Developer Primer for SPA

Finalmente, como siempre hemos querido demostrar como hacerlo nosotros mismos sin necesidad de descargar nada, ni en el servidor ni en el cliente, ya que esto aumenta el tamaño de la aplicación perjudicando el ancho de banda, es decir, la performance.

Descarga del Código
SinglePageApplication

martes, 20 de enero de 2015

El Demo del Día: TreeView con CheckBox en ASP.NET MVC

TreeView con CheckBox en ASP.NET MVC

Introducción a ASP.NET MVC

El Modelo Vista Controlador es un Modelo o Patrón de Arquitectura de Desarrollo de Software que permite la separación de la lógica en 3 componentes:
- El Modelo: Contiene la lógica del dominio, como las entidades del negocio.
- La Vista: Representa la interface de usuario de la aplicación, por ejemplo las páginas y controles.
- El Controlador: Controla la interacción del usuario con la vista y la asocia a un modelo.

ASP.NET MVC es la implementación de Microsoft de este modelo o patrón como alternativa a los WebForms de ASP.NET, el cual presenta las siguientes ventajas:
- Facilita la administración de la complejidad al separar la lógica en 3 componentes.
- Reduce el HTML enviado al cliente al no usar el estado de vista (ViewState)
- Proporciona una mayor compatibilidad con el desarrollo basado en pruebas (TDD), etc.

A partir de ASP.NET MVC 3 podemos elegir crear las vistas usando 2 motores:
- WebForm: Es el mismo que se usa para crear los Sitios ASP.NET con WebForms, es decir para el código incrustado del servidor se usa: <%= %>, <%: %> o <%# %>.
- Razor: Es un nuevo motor creado especialmente para aplicaciones MVC y usa código incrustado del servidor mediante @.
Nota: Se recomienda usar Razor como motor de vista predeterminado, ya que su sintaxis es mas corta y maneja mejor el tema de codificación y de-codificación.

Para los que recién inician con ASP.NET MVC el inconveniente principal aparte de acostumbrarse al nuevo modelo, es la falta de variedad de controles para crear las vistas, ya que los controles que ofrece Microsoft son los Helpers (no son muchos) que se clasifican en 3:
- HTML Helpers: Form, Label, TextBox, CheckBox, ListBox, DropDownList, ActionLink, etc.
- AJAX Helpers: Form, ActionLink, RouteLink y Script.
- URL Helpers: Action, Content, Encode, HttpRouteUrl.

Quizás los controles que mas extrañen los programadores es los enlazados a datos como GridView, DataList, Repeater, ListView, TreeView, Chart, etc. Aunque si bien es cierto no vienen como Helpers se pueden implementar en forma personalizada, por ejemplo en este primer post de MVC trataremos sobre como crear un TreeView con CheckBox.

Requerimiento

Se desea mostrar una lista de empleados en forma jerárquica de acuerdo a su cargo, para lo cual cada empleado tiene un único jefe. La aplicación debe permitir seleccionar un empleado y automáticamente deberá seleccionarse todos sus dependientes.
Nota: La aplicación debe ser Web y estar en ASP.NET MVC4.

Solución

Para cubrir estos requerimientos se creará un TreeView con CheckBox para lo cual se realizará lo siguiente:
- El el Modelo se creará una Entidad llamada "beEmpleado".
- En el Controlador se creará un método "obtenerEmpleados" que llene una lista con los empleados.
- En el Controlador se creará un método de acción llamado "Lista" que devuelva una vista (ViewResult).
- En el Controlador se creará un método de acción llamado "Listar" que devuelva la lista en formato JSON (JsonResult).
- Desde la Vista "Lista", al cargar la página usando jQuery Ajax se llamará al método "Listar" que devuelve los datos como JavaScript Object Notation (JSON).
- Mediante JavaScript mostraremos los datos en una Tabla
- Mediante jQuery mostraremos los datos en un div creando una lista con viñetas (ul - li) conteniendo CheckBoxs.
- Usando jQuery se programará la selección jerárquica, es decir al marcar o desmarcar un empleado, debe expandirse a todos sus subordinados.
- Usando jQuery se programará el expandir o colapsar un nodo (empleado) del TreeView.

Crear una Aplicación Web de ASP.NET MVC4 en C#

Abrir el Visual Studio 2012 y seleccionar un nuevo proyecto de tipo: "Aplicación web de ASP.NET MVC4", tal como se muestra en la siguiente figura:


Se mostrará una ventana para seleccionar la plantilla de proyecto, similar a la mostrada en la siguiente figura:


Seleccionar la opción "Vacio" y como motor de vista "Razor" y "Aceptar". En la ventana del Explorador de Soluciones se verá la siguiente estructura de carpetas:


Nota: Apreciar como viene predefinida las carpetas para los Controladores, los Modelos y las Vistas.
Además viene una carpeta App_Start para configurar los inicios de la aplicación.

Crear un Modelo con la Entidad del Empleado

Clic derecho a la carpeta Models y seleccionar "Agregar" y luego "Clase", llamarle al archivo "beEmpleado.cs" y escribir el siguiente código:

namespace TreeView_CheckBox.Models
{
    public class beEmpleado
    {
        public int IdEmpleado { get; set; }
        public string Nombres { get; set; }
        public int IdJefe { get; set; }
    }
}

Crear un Controlador para el Empleado

Clic derecho a la carpeta Controllers y seleccionar "Agregar" y luego "Controlador" y se mostrará una ventana similar a la siguiente figura:


Llamarle al archivo "EmpleadoController.cs" y en opciones de plantillas dejarlo en plantilla vacia (Vaciar Controlador MVC). Luego escribir el siguiente código:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TreeView_CheckBox.Models;

namespace TreeView_CheckBox.Controllers
{
    public class EmpleadoController : Controller
    {
        List<beEmpleado> lbeEmpleado;

        private void obtenerEmpleados()
        {
            lbeEmpleado = new List<beEmpleado>();
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 1, Nombres = "Luis Dueñas",
                                          IdJefe = 0 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 2, Nombres = "Arturo Castañeda",
                                          IdJefe = 1 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 3, Nombres = "Enrique Espinal",
                                          IdJefe = 1 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 4, Nombres = "Maria Rojas",
                                          IdJefe = 2 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 5, Nombres = "Juan Perez",
                                          IdJefe = 2 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 6, Nombres = "Rosa Toro",
                                          IdJefe = 3 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 7, Nombres = "Pedro Vasquez",
                                          IdJefe = 3 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 8, Nombres = "Cesar Ramirez",
                                          IdJefe = 5 });
            lbeEmpleado.Add(new beEmpleado { IdEmpleado = 9, Nombres = "Ana Rodriguez",
                                          IdJefe = 6 });
        }

        public ViewResult Lista()
        {
            return View();
        }

        public JsonResult Listar()
        {
            JsonResult rpta;
            obtenerEmpleados();
            rpta = Json(lbeEmpleado, JsonRequestBehavior.AllowGet);
            return rpta;
        }
    }
}

Crear una Hoja de Estilos para la Vista

Primero crear una carpeta llamada "Content", luego clic derecho "Agregar" y luego "Hoja de estilos" y como nombre llamarle "ACME.css" y escribir el siguiente código:

body {
    background-color:lightgray;
}
.Titulo {
    background-color:black;
    color:white;
    font-size:x-large;
    text-transform:uppercase;
}
.Subtitulo {
    background-color:white;
    color:black;
    font-size:large;
    text-transform:capitalize;
}
.AnchoTotal {
    width:100%;
}
.FilaCabecera {
    background-color:gray;
    color:white;
}
.FilaDatos {
    background-color:white;
    color:blue;
}

Crear la Vista para mostrar los datos

Ir al controlador y ubicarse sobre el método "Lista" (acción), clic derecho y seleccionar "Agregar vista", aparecerá un diálogo como se muestra en la siguiente figura:


Desmarcar todas las casillas (checkboxs) y agregar la vista llamada "Lista", luego escribir el siguiente código:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Lista</title>
    <link href="~/Content/ACME.css" rel="stylesheet" />
    <link href="~/Content/TreeView.css" rel="stylesheet" />
</head>
<body>
    <div>
        <table class="AnchoTotal">
            <tr class="Titulo">
                <td colspan="2">TreeView con CheckBox en ASP.NET MVC usando
                                             JSON, jQuery y Ajax</td>
            </tr>
            <tr class="Subtitulo">
                <td colspan="2">Lista de Empleados</td>
            </tr>
            <tr>
                <td style="width:50%">
                    <table class="AnchoTotal">
                        <thead>
                            <tr class="FilaCabecera">
                                <td style="width:100px">Id Emp</td>                        
                                <td style="width:300px">Nombres</td>
                                <td style="width:100px">Id Jefe</td>
                            </tr>
                        </thead>
                        <tbody id="tblEmpleado">
                        </tbody>
                    </table>
                </td>
                <td style="width:50%; vertical-align:top">
                    <div id="divEmpleado">
                        <ul id="ulEmpleado"></ul>
                    </div>
                </td>
            </tr>
        </table>
    </div>
    <script src="~/Scripts/jquery-1.8.2.min.js"></script>
    <script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
    <script src="~/Scripts/Rutinas.js"></script>
    <script>cargarLista();</script>
</body>
</html>

Crear el archivo JavaScript con el código cliente para el TreeView

Antes que nada crear una carpeta llamada "Scripts" y arrastrar del explorador de Windows los archivos de jQuery: "jquery-1.8.2.min.js" y "jquery.unobtrusive-ajax.min.js", luego agregar un archivo de JavaScript llamado "Rutinas.js" y escribir el siguiente código:

function cargarLista() {
    $.ajax(
        {
            url: "Empleado/Listar/",
            type: "post",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: exito,
            error: error
        });
}

function mostrarTabla(rpta) {
    var tabla = "";
    for (i = 0; i < rpta.length; i++) {
        tabla += "<tr class='FilaDatos'><td>" + rpta[i].IdEmpleado + "</td><td>" +
            rpta[i].Nombres + "</td><td>" + rpta[i].IdJefe + "</td></tr>";
    }
    var tbl = document.getElementById("tblEmpleado");
    tbl.innerHTML = tabla;
}

function mostrarTreeCheck(rpta) {
    var ul = $("#ulEmpleado");
    for (var i = 0; i < rpta.length; i++) {
        var li = "<li data-id='" + rpta[i].IdEmpleado + "'><input type='checkbox' />
                      <span style='cursor:pointer'>" + rpta[i].Nombres + "</span></li>";
        var padre;
        if (rpta[i].IdJefe == "0") padre = ul;
        else {
            var $elem = ul.find("li[data-id='" + rpta[i].IdJefe + "']");
            if ($elem.find("ul").length == 0) $elem.append("<ul>");
            padre = $elem.find("ul:first");
        }
        padre.append(li);
    }
}

function seleccionarTreeCheck() {
    $(function () {
        $("input[type='checkbox']").change(function () {
            $(this).siblings('ul')
                   .find("input[type='checkbox']")
                   .prop('checked', this.checked);
        });
    });
}

function expandirColapsarTreeCheck() {
    $(function () {
        $('#ulEmpleado').find('span').click(function (e) {
            $(this).parent().children('ul').toggle();
        });
    });
}

function exito(rpta) {
    mostrarTabla(rpta);
    mostrarTreeCheck(rpta);
    seleccionarTreeCheck();
    expandirColapsarTreeCheck();
}

function error(rpta) {
    alert(rpta.statusText);
}

Configurar el inicio y ejecutar la aplicación web

Para probar la aplicación web debemos configurar el inicio para lo cual nos vamos a la carpeta "App_Start" y abrimos el archivo "RouteConfig.cs" cambiando el nombre del controlador y la acción tal como se muestra en el siguiente código:

using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace JS01_TreeView_CheckBox
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Empleado", action = "Lista", id = UrlParameter.Optional }
            );
        }
    }
}

Finalmente, grabar y pulsar F5 para ejecutar la aplicación, mostrándose el resultado similar a la siguiente figura:


Seleccionar el primer empleado y ver como se marcan todos los empleados, tal como se muestra en la siguiente figura:


Dar clic sobre el segundo empleado y notar como se colapsa (oculta) sus subordinados, también colapsar el tercer empleado y el resultado será similar a la siguiente figura:


Comentario Final

En este post, un poco grande, hemos querido iniciar los Demos dedicados a ASP.NET MVC, empezando por la creación de un control TreeView con CheckBox que seleccione en forma jerárquica y expanda y colapse sus elementos.

Un camino hubiera sido usar Librerías de Controles de terceros como jQueryUI, Telerik KendoUI, Infragistics, DevExpress, etc. Pero como siempre el objetivo de este blog es enseñar a hacerlo uno mismo, para lo cual usamos JSON, JavaScript, jQuery y Ajax.

Espero les guste y si es así lo pueden re-postear en sus redes sociales: Google+, Facebook, Twitter, etc.

Descarga
2015_01_20_DemoDia_TreeView_CheckBox