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

lunes, 25 de julio de 2016

Artículo: Temas a Aprender en un Lenguaje de Programación

Temas a Aprender en un Lenguaje de Programación

1. Introducción

Un Lenguaje de Programación es el medio por el cual los programadores dan ordenes al computador y sin importar que tipo de lenguaje estén usando todos ellos sirven para crear aplicaciones. En este artículo quiero compartir mi opinión sobre que temas deben aprenderse al momento de elegir un Lenguaje de Programación.

He tratado de hacer una especie de Syllabus genérico para cualquier Lenguaje de Programación, por ejemplo los temas lo puedes ver en cualquier lenguaje del servidor como C# en .NET, PHP, Phyton, Ruby, C++, etc. Pero también la mayoría de temas se pueden ver en JavaScript.

Este breve artículo servirá para que tanto estudiantes y profesionales sepan los temas que son necesarios y los mas útiles que deben conocer, por lo que se ha divido en 3 partes con 4 capítulos cada una: Básica, Intermedia y Avanzada.

2. Temas o Tópicos a Aprender

Parte Básica

1. Estructuras de Datos
1.1. Simples: Numéricas, Cadenas, Lógicas, Fecha, etc.
1.2. Complejas: Arreglos, Listas, Pilas, Colas, Arboles, etc.
1.2. Objetos: Clases, Intefaces, Propiedades, Métodos, Eventos, etc.

2. Estructuras de Control de Flujo
2.1. Condicionales: if, switch, case, etc.
2.2. Repetitivas o de Bucle: for, while, do..while, etc.
2.3. Control de Errores: try..catch

3. Creando Interfaces de Usuario (IU)
3.1. Formularios
3.2. Controles de Entrada: TextBox, Radio, Check
3.3. Controles de Ejecución: Button, LinkButton
3.4. Controles de Imagen: Image, ImageButton
3.4. Controles de Listas: ListBox, ComboBox
3.5. Controles de Vistas: GridView, TreeView, ListView
3.6. Otros Controles: Calendarios, Banners, Visores, etc.

4. Manejo de Entrada y Salida
4.1. Información del Sistema: Directorios, Rutas y Archivos
4.2. Lectura y Escritura: Archivos Secuenciales y Aleatorios
4.3. Codificación de Datos: Codificar y Decodificar datos
4.4. Manejo de Expresiones Regulares

Parte Intermedia

5. Acceso a Base de Datos (Conectado)
5.1. Conectarse a una Base de Datos
5.2. Ejecutar Comandos SQL: Select, Insert, Update, Delete
5.3. Trabajar con Procedimentos Almacenados

6. Manejo de Datos (Desconectado)
6.1. Consultas: Filtros y Búsquedas
6.2. Ordenación: Ascendente y Descendente
6.3. Paginación: Por Filas y Por Columnas
6.4. Transferencia: Importación y Exportación

7. Presentación o Visualización de Datos
7.1. Vistas: Tablas, Cabecera Detalle, Jerárquicas y Tabla Cruzada
7.1. Reportes: Por Código y Por Herramientas
7.2. Gráficos: Por Código y Por Controles
7.3. Impresiones: Presentación Preliminar, Configurar Pagina, Imprimir

8. Pruebas de la Aplicación
8.1. Pruebas Unitarias: Funcionalidad
8.2. Pruebas de Rendimiento: Velocidad
8.3. Pruebas de Disponibilidad: Continuidad
8.4. Pruebas de Seguridad: Protección

Parte Avanzada

9. Programación de la Reusabilidad
9.1. Módulos o Librerías de Clases
9.2. Módulos o Librerías de Controles

10. Programación Asíncrona
10.1. Subprocesamiento: Threads y ThreadPool en una CPU
10.2. Programación Paralela: Tareas en Múltiples CPU

11. Programación de Redes y Distribuida
11.1. Sockets: TCP, UDP
11.2. Web: HTTP (Get, Post, Put, Delete)
11.3. Web Sockets: WS
11.4. Servicios: RPC, SOAP, REST (HTTP)
11.5. Correos: IMAP, POP3, SMTP
11.6. Mensajería: AMQP, MQTT, STOMP
11.7. Archivos: FTP
11.8. Señales: STUN, TURN, ICE, NAT

12. Criptografía o Cifrado de Datos
12.1. Cifrado Simétrico: AES, DES, RC2, Rijndael, Triple DES, etc.
12.2. Cifrado Asimétrico: DSA, ECDiffieHellman, ECDSA, RSA, etc.
12.3. Valores Hash: MD5, RIPEMD160, SHA1, SHA256, SHA512, etc.
12.4. Firmas Digitales y Tokens

3. Comentario Final

Parte Básica

Los Institutos y Universidades que enseñan como curso oficial o electivo en pre-grado un Lenguaje de Programación deberían cubrir la parte básica, pero pasan mucho tiempo en los 3 primeros temas y se olvidan del manejo de entrada y salida, sobre todo del manejo de archivos y después cuando los alumnos son profesionales y trabajan no pueden leer cualquier tipo de archivo, excepto el de Texto: TXT, XML, JSON, CSV, pero no un Binario (DOC, XLS, EXE, DLL, etc)  o uno Comprimido (XLSX, DOCX, PPTX, etc.)

También noto muchos problemas en los programadores en los temas de Codificación de Datos (Encoding), Decodificación de Datos (Decoding) y Búsqueda de Patrones de Texto (Expresiones Regulares). Con una buena base educativa no tendría porque haber ningún tipo de problemas al desarrollar una aplicación en cualquier lenguaje.

Parte Intermedia

La parte intermedia esta dirigida a los profesionales que trabajan desarrollando aplicaciones y necesitan conocer los temas de acceso a datos (conectado) y manejo de datos (desconectado), presentación de datos y pruebas. Aquí la falla está en que se da mucho énfasis a la programación conectada pero No se entiende que ésta es la causante de que en las empresas "Los Sistemas están Lentos" porque "La Red está Lenta" porque "las aplicaciones realizan muchas conexiones" (miles por día), por lo que es "Indispensable" saber el manejo "Desconectado" con los datos.

En cuanto a la presentación de datos la mayoría de programadores solo saben "Herramientas de Reportes", por ejemplo "Crystal Reports" o "Report Viewer" (Reporting Services) o para crear Gráficos usan "Controles", abren instancias de aplicaciones como Word y Excel. Todas estas técnicas descritas son ineficientes ya que consumen mucha memoria y son lentas, hay otras formas de hacer reportes "super rápidos", por ejemplo en .NET para Windows se usa PrintDocument y en Web solo basta con HTML y JavaScript.

En cuanto a las Pruebas, los instructores solo saben enseñar "Pruebas Unitarias" que es lo mínimo que debe pedirse de la aplicación: que cumpla con la funcionalidad pedida, pero hay temas más técnicos como son la Performance o Rendimiento, la Disponibilidad como la tolerancia a Fallas de Red y la Seguridad (privacidad de datos, ataques, robo de información, etc.) que No se toman en cuenta. Es por esto que a cada momento vemos en todas partes "Sistemas Lentos", "Sistemas Caídos por Falta de Red", "Ataques a Sitios Web", "Robo de Datos", etc.

Parte Avanzada

En esta última parte si que estamos peor (según mi experiencia de mas de 25 años como programador e instructor), ya que los 4 últimos temas es poco probable que se enseñe en una capacitación tradicional, excepto Web HTTP (REST) y Servicios SOAP (porque está de moda), pero temas como crear tu propia librería de clases y controles o tu propio módulo de clases y controles Nunca se ve, solo se les enseña a usar lo que ya está hecho sin  siquiera ser selectivo con lo que se usa (solo extraer lo necesario del código o control).

Otro problema de muchos programadores es que No saben el "ABC" de la programación asíncrona, muchos piensan que solo se puede implementar en la web con AJAX, jQuery o cualquier Framework popular, cuando en la web en el lado del cliente puede usarse XHR (nativo) y en el servidor Threads, ThreadPool, Delegados-CallBacks, Tasks, etc. Es mas importante que apliques asíncrono al servidor que al cliente porque la del cliente es para dar una mejor "Experiencia de Usuario" y la del servidor es para que "No se quede Colgado", y al final vas a dar la peor experiencia al usuario.

En cuanto al tema de la programación de redes o distribuida, la mayoría desconoce el poder de los Sockets y Web Sockets para hacer comunicación bidireccional en tiempo real y solo saben la peor (Servicios SOAP: Unidireccional). También es necesario aprender a manejar archivos con FTP, correos con SMTP, colas con STOMP, Señales con STUN, etc.

Finalmente, el tema de la Seguridad es muy importante y parte de esta es el cifrado de datos como claves, contenido, archivos, etc. Es necesario conocer los 4 tipos de tareas criptográficas mas comunes: cifrado simétrico y cifrado asimétrico (bidireccionales), valores hash (unidireccionales) y Firmas Digitales.

En General

En General, el Comentario Final es que si queremos mejorar nuestro nivel sea que somos estudiantes o profesionales debemos saber cuales son los temas mas importantes en nuestra formación, siento que en todos los niveles de la educación: pre-grado (para estudiantes) y especialización (para profesionales) los temas que se enseñan no son los mas importantes para el trabajo. Se da mucho énfasis en patrones y reusabilidad ("Construye Fácil") pero no en lo mas importante: en Producción que sea "Veloz", "Seguro" y "Siempre Disponible".

Mi aporte en estos últimos años ha sido cambiar esa mentalidad de "lo fácil" (reusabilidad) por lo "fácil mas lo eficiente" (performance y si se puede reusabilidad), aunque me hubiese gustado llegar a mas gente (aunque sea en mi país), es por eso, que a través de este Blog y mi Canal de YouTube trato de compensar este déficit.

Espero que con este artículo logre contribuir a que los centros de enseñanza de Lenguajes o Herramientas de Programación tomen en cuenta los temas que son necesarios enseñar para tener mejores profesionales que nunca tengan problemas al momento de trabajar o si los tienen que los resuelvan de la mejor manera y lo mas rápido posible.

miércoles, 15 de julio de 2015

Videos - Curso ASP.NET MVC Editora Perú (Parte 2)

Videos del Curso de ASP.NET MVC en Editora Perú (Parte 2)

Segunda parte del curso de ASP.NET MVC con Demos muy buenos, por ejemplo varias formas de paginación: conectada, desconectada parcial y desconectada total, además de una aplicación que incluye un Login cifrado y una consulta y actualización de empleados, incluyendo su foto.

Demo 16 - Paginación Conectada Asincrona con XmlHttpRequest y String

En este video se muestra como paginar en forma conectada y asíncrona, es decir, se obtiene cada pagina desde la base de datos (con un procedimiento almacenado) y luego este es enviado como una cadena al cliente.

La llamada de este método se hace en JavaScript en forma asíncrona con XmlHttpRequest y se forma el HTML dinamicamente con los datos (string) devuelto por el servidor.

Esta técnica debe usarse cuando los datos a consultar deben hacerse en línea, ya que varian constantemente, por ejemplo, el stock de los productos.


Demo 17 - Paginación Desconectada Parcial Asincrona

En este video se muestra como paginar en forma desconectada parcial y asíncrona, es decir, una sola vez se hace el envio de datos desde el Servidor de Datos al Servidor Web y se guarda en un objeto TempData.

Se crea un método (acción) en el Controlador que permite Paginar, recuperando del TempData los datos y devolviendo los datos de una sola pagina en forma de cadena.

La llamada de este método se hace en JavaScript en forma asíncrona con XmlHttpRequest y se forma el HTML dinamicamente con los datos (string) devuelto por el servidor.

Esta técnica debe usarse cuando los datos a consultar no se necesitan en línea (desconectado) y son muchos registros (mas de 1000 por ejemplo).


Demo 18 - Paginación Desconectada Total Asincrona

En este video se muestra como paginar en forma desconectada total y asíncrona, es decir, una sola vez se hace el envio de datos desde el Servidor de Datos al Servidor Web y de éste al Cliente.

Se envian como cadenas los datos de los productos y en el cliente usando JavaScript se forma el HTML de la tabla y los índices de paginas y se asocia a una función de JavaScript que permite paginar.

Esta técnica debe usarse cuando los datos a consultar no se necesitan en línea (desconectado) y son pocos registros (menos de 1000 por ejemplo).

La gran ventaja de esta técinca es que si se cae el Servidor Web o el Servidor de Datos no afectaría a la pagina ya que funciona todo localmente.


Demo 19 - Login, Consulta y Actualización con Foto (Parte 1)

En esta primera parte, se muestra un video de como crear un Login usando un Filtro de Autenticación validando  mediante un objeto de Sesión.

El login corresponde al usuario asignado a un cliente y esta cifrado usando JavaScript mediante el algoritmo hash MD5 implementado en la librería creada por Google CryptoJS.


Demo 19 - Login, Consulta y Actualización con Foto (Parte 2)

En esta segunda parte se muestra como crear una Consulta de Empleados por código, la cual incluye los datos del Apellido, Nombre, Fecha de Nacimiento y la Foto del Empleado.


Demo 19 - Login, Consulta y Actualización con Foto (Parte 3)

En esta tercera parte del video se muestra como actualizar los datos del empleado (incluyendo la foto) en forma asíncrona usando XmlHttpRequest mediante el método "post" y un FormData.

Para grabar la foto se envía como cadena (base 64) pero sin cabecera, pero en el servidor se convierte a array de bytes y luego se pasa a la entidad de negocio y se envia a la regla de negocio que permite actualizar los datos del empleado, incluyendo la foto.


Lo destacado de todos los demos es que son asíncronos y consumen el menor ancho de banda, ya que uso mi propio serializador de cadenas y uso XHR (asíncrono nativo).

martes, 7 de julio de 2015

Videos - Curso ASP.NET MVC Editora Perú (Parte 1)

Videos del Curso de ASP.NET MVC en Editora Perú (Parte 1)

Comparto la primera parte del Curso de ASP.NET MVC realizado en Editora Perú (Diario El Peruano y Agencia de Noticias Andina), en donde casi todos los demos son en forma asíncrona con la mejor performance (XmlHttpRequest y Strings).

Demo 10 - Consulta Conectada Sincrona con Todo el HTML

En este video se muestra una aplicación que permite filtrar los productos por categoría en forma conectada, es decir, consultando en cada momento a la base de datos usando librerías.

Para mostrar los datos del filtro se vuelve a mostrar la Vista completa, es decir todo el HTML, por lo cual se ve el parpadeo.


Demo 11 - Consulta Conectada Asincrona con Ajax Form y Vista Parcial

En este video se muestra una aplicación que permite filtrar los productos por categoría en forma conectada, es decir, consultando en cada momento a la base de datos usando librerías.

A diferencia del demo anterior, la consulta es asíncrona usando un Formulario Ajax y una Vista Parcial que solo muestra la tabla de productos, por lo que no ocurre el parpadeo.


Demo 12 - Consulta Conectada Asincrona con jQuery Ajax y JSON

En este video se muestra una aplicación que permite filtrar los productos por categoría en forma conectada, es decir, consultando en cada momento a la base de datos usando librerías.

A diferencia del demo anterior, la consulta es asíncrona usando jQuery Ajax y JSON que disminuye los datos enviados al cliente en casi la mitad con respecto a la vista parcial.


Demo 13 - Consulta Conectada Asincrona con jQuery Ajax y String

En este video se muestra una aplicación que permite filtrar los productos por categoría en forma conectada, es decir, consultando en cada momento a la base de datos usando librerías.

A diferencia del demo anterior, la consulta es asíncrona usando jQuery Ajax y Strings para lo cual se crea un Serializador que permite convertir la Lista de Objetos en Cadenas separadas por un delimitador de campos y otro de registros.

Esta técnica permite reducir los datos enviados al cliente en casi la tercera parte con respecto a JSON, es decir, el HTML es el 100%, Vista Parcial 50%, JSON 25% y Strings 8%. Esta última tecnica que propongo es la máxima en Performance.


Demo 14 - Consulta Desconectada Parcial Asincrona con jQuery Ajax y String

En este video se muestra una aplicación que permite filtrar los productos por categoría en forma desconectada parcial, es decir, desconectada de la base de datos, pero conectada al servidor web.

La consulta es asíncrona usando jQuery Ajax y Strings para lo cual se crea un Serializador que permite convertir la Lista de Objetos en Cadenas separadas por un delimitador de campos y otro de registros.

En el Servidor Web los datos se guardan en un TempData al inicio y luego se recuperan cada vez que se filtra, viajando solo una cadena conteniendo los productos por categoría.


Demo 15 - Consulta Desconectada Total Asincrona con jQuery Ajax y String

En este video se muestra una aplicación que permite filtrar los productos por categoría en forma desconectada total, es decir, desconectada de la base de datosy del servidor web.

La consulta es asíncrona usando jQuery Ajax y Strings para lo cual se crea un Serializador que permite convertir la Lista de Objetos en Cadenas separadas por un delimitador de campos y otro de registros.

Todos los datos de categorias y productos se envian al cliente, pero solo se guardan los productos para poder filtrarse por JavaScript.


Los alumnos que alguna vez llevaron conmigo ASP.NET MVC, se daran cuenta que la forma como estamos programando es un poco diferente, ya que uso mas JavaScript y menos C#.

martes, 24 de marzo de 2015

El Demo del Día: Graficar Datos en el Servidor en ASP.NET MVC

Graficar Datos en el Servidor en ASP.NET MVC con llamada asíncrona usando Ajax Form y Vista Parcial

Requerimiento

Se desea crear una aplicación web que permita consultar los productos por categoría y mostrar los datos mas gráficos de diferentes tipos: Barras, Columnas, Lineas y Pie, pero el requisito es que sea conectado o en línea, es decir, el filtro por categoría debe hacerse directo de la base de datos y el gráfico debe crearse dinámicamente en el servidor web.

Solución

- Crear una aplicación en ASP.NET MVC con un método de acción que se conecte a la BD para traer la lista de categorías mas los tipos de gráficos.
- Crear un formulario MVC Ajax que realice una llamada asíncrona cada vez que se selecciona una categoría que llama a una acción que haga la consulta en base de datos y que cree el gráfico dinámicamente devolviendo una vista parcial.
- Para crear los diferentes tipos de gráficos usaremos la librería System.Drawing y el gráfico lo almacenaremos en un MemoryStream, a partir del cual obtendremos su array de bytes y lo almacenaremos en un ViewBag llamado Imagen con el contenido de la imagen en formato base64.

Crear los Procedimientos Almacenados en la Base de Datos Northwind de SQL Server

Para el ejemplo usaremos la Base de Datos Northwind de SQL Server, en la cual crearemos los siguientes Procedimiento almacenado:

Create Procedure [dbo].[uspCategoriesListar]
As
Select CategoryID,CategoryName From Categories
Go

Create Procedure [dbo].[uspProductsListarPorCategoria]
@CategoryId int
As
Select ProductID,ProductName,SupplierID,
CategoryID,UnitPrice,UnitsInStock
From Products
Where CategoryId=@CategoryId

Crear la Librería de Clases de Entidades del Negocio

Crear la librería de clases llamada: "Northwind.Librerias.EntidadesNegocio" y agregar la clase "beCategoria.cs":

namespace Northwind.Librerias.EntidadesNegocio
{
    public class beCategoria
    {
        public int IdCategoria { get; set; }
        public string Nombre { get; set; }
    }
}

Agregar otra clase a la librería llamada "beProducto.cs":

namespace Northwind.Librerias.EntidadesNegocio
{
    public class beProducto
    {
        public int IdProducto { get; set; }
        public string Nombre { get; set; }
        public int IdProveedor { get; set; }
        public int IdCategoria { get; set; }
        public decimal PrecioUnitario { get; set; }
        public short Stock { get; set; }
    }
}

Grabar y compilar la Librería de Entidades del Negocio.

Crear la Librería de Acceso a Datos

Crear la librería de clases llamada: "Northwind.Librerias.AccesoDatos", referenciar a la librería de clases de entidades creada anteriormente y agregar la clase "daCategoria.cs" y escribir el siguiente código:

using System;
using System.Collections.Generic; //List
using System.Data; //CommandType, CommandBehavior
using System.Data.SqlClient; //SqlConnection, SqlCommand, SqlDataReader
using Northwind.Librerias.EntidadesNegocio; //beCategoria

namespace Northwind.Librerias.AccesoDatos
{
    public class daCategoria
    {
        public List<beCategoria> listar(SqlConnection con)
        {
            List<beCategoria> lbeCategoria = null;

            SqlCommand cmd = new SqlCommand("uspCategoriesListar", con);
            cmd.CommandType = CommandType.StoredProcedure;
            SqlDataReader drd = cmd.ExecuteReader();
            if (drd != null)
            {
                lbeCategoria = new List<beCategoria>();
                beCategoria obeCategoria;
                int posIdCat = drd.GetOrdinal("CategoryID");
                int posNomCat = drd.GetOrdinal("CategoryName");
                while (drd.Read())
                {
                    obeCategoria = new beCategoria();
                    obeCategoria.IdCategoria = drd.GetInt32(posIdCat);
                    obeCategoria.Nombre = drd.GetString(posNomCat);
                    lbeCategoria.Add(obeCategoria);
                }
                drd.Close();
            }
            return (lbeCategoria);
        }
    }
}

Agregar una nueva clase a la librería llamada "daProducto.cs" y escribir el siguiente código:

using System;
using System.Collections.Generic; //List
using System.Data; //CommandType, CommandBehavior
using System.Data.SqlClient; //SqlConnection, SqlCommand, SqlDataReader
using Northwind.Librerias.EntidadesNegocio; //beProducto

namespace Northwind.Librerias.AccesoDatos
{
    public class daProducto
    {
        public List<beProducto> listarPorCategoria(SqlConnection con,int idCategoria)
        {
            List<beProducto> lbeProducto = null;

            SqlCommand cmd = new SqlCommand("uspProductsListarPorCategoria", con);
            cmd.CommandType = CommandType.StoredProcedure;

            SqlParameter par = cmd.Parameters.Add("@CategoryId", SqlDbType.Int);
            par.Direction = ParameterDirection.Input;
            par.Value = idCategoria;

            SqlDataReader drd = cmd.ExecuteReader(CommandBehavior.SingleResult);
            if (drd != null)
            {
                lbeProducto = new List<beProducto>();
                int posIdProducto = drd.GetOrdinal("ProductID");
                int posNombre = drd.GetOrdinal("ProductName");
                int posIdProveedor = drd.GetOrdinal("SupplierID");
                int posIdCategoria = drd.GetOrdinal("CategoryID");
                int posPrecioUnitario = drd.GetOrdinal("UnitPrice");
                int posStock = drd.GetOrdinal("UnitsInStock");
                beProducto obeProducto;
                while (drd.Read())
                {
                    obeProducto = new beProducto();
                    obeProducto.IdProducto = drd.GetInt32(posIdProducto);
                    obeProducto.Nombre = drd.GetString(posNombre);
                    obeProducto.IdProveedor = drd.GetInt32(posIdProveedor);
                    obeProducto.IdCategoria = drd.GetInt32(posIdCategoria);
                    obeProducto.PrecioUnitario = drd.GetDecimal(posPrecioUnitario);
                    obeProducto.Stock = drd.GetInt16(posStock);
                    lbeProducto.Add(obeProducto);
                }
                drd.Close();
            }

            return (lbeProducto);
        }
    }
}

Grabar y compilar la librería de acceso a datos creada.

Crear la Librería de Reglas del Negocio

Crear la librería de clases llamada: "Northwind.Librerias.ReglasNegocio", referenciar a la librería de clases de entidades y también a la de acceso a datos, luego agregar la clase "brCategoria.cs" y escribir el siguiente código:

using System;
using System.Data.SqlClient; //SqlConnection
using System.Collections.Generic; //List
using Northwind.Librerias.EntidadesNegocio; //beCategoria
using Northwind.Librerias.AccesoDatos; //daCategoria

namespace Northwind.Librerias.ReglasNegocio
{
    public class brCategoria
    {
        public List<beCategoria> listar()
        {
            List<beCategoria> lbeCategoria = null;
            string CadenaConexion = ConfigurationManager.ConnectionStrings["conNW"]
                                                     .ConnectionString;
            using (SqlConnection con = new SqlConnection(CadenaConexion))
            {
                try
                {
                    con.Open();
                    daCategoria odaCategoria = new daCategoria();
                    lbeCategoria = odaCategoria.listar(con);
                }
                catch (SqlException ex)
                {
                    //grabarLog(ex);
                }
                catch (Exception ex)
                {
                    //grabarLog(ex);
                }
            } //con.Close(); con.Dispose();
            return (lbeCategoria);
        }
    }
}

Agregar una nueva clase a la librería llamada "brProducto.cs" y escribir el siguiente código:

using System;
using System.Data.SqlClient; //SqlConnection
using System.Collections.Generic; //List
using Northwind.Librerias.EntidadesNegocio; //beProducto
using Northwind.Librerias.AccesoDatos; //daProducto

namespace Northwind.Librerias.ReglasNegocio
{
    public class brProducto
    {
        public List<beProducto> listarPorCategoria(int idCategoria)
        {
            List<beProducto> lbeProducto = null;
            string CadenaConexion = ConfigurationManager.ConnectionStrings["conNW"]
                                                     .ConnectionString;
            using (SqlConnection con = new SqlConnection(CadenaConexion))
            {
                try
                {
                    con.Open();
                    daProducto odaProducto = new daProducto();
                    lbeProducto = odaProducto.listarPorCategoria(con,idCategoria);
                }
                catch (SqlException ex)
                {
                    //grabarLog(ex);
                }
                catch (Exception ex)
                {
                    //grabarLog(ex);
                }
            } //con.Close(); con.Dispose();
            return (lbeProducto);
        }
    }
}

Nota: También es necesario hacer una referencia a la librería "System.Configuration" para leer la cadena de conexión definida en la aplicación.

Grabar la librería de reglas de negocio creada y compilarla.

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

Seleccionar un nuevo proyecto de tipo: "Aplicación web de ASP.NET MVC4" y escribir como nombre "Demo10", luego seleccionar la opción "Vacio" y como motor de vista "Razor" y "Aceptar".

Nota: Antes de iniciar con el código hay que referenciar a las librerías creadas, sobre todo a la Regla de Negocio y las Entidades de Negocio.

Crear un Controlador para el Producto

Clic derecho a la carpeta Controllers y seleccionar "Agregar" y luego "Controlador", llamarle al archivo "ProductoController.cs" y en opciones de plantillas dejarlo en plantilla vacía (Vaciar Controlador MVC). Luego escribir el siguiente código:

using System;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Northwind.Librerias.EntidadesNegocio;
using Northwind.Librerias.ReglasNegocio;

namespace Demo10.Controllers
{
    public class ProductoController : Controller
    {        
        public ActionResult Lista()
        {
            brCategoria obrCategoria = new brCategoria();
            List<beCategoria> lbeCategoria = obrCategoria.listar();
            ViewBag.Categorias = lbeCategoria;
            List<string> tiposGrafico = new List<string>();
            tiposGrafico.Add("Barras");
            tiposGrafico.Add("Columnas");
            tiposGrafico.Add("Lineas");
            tiposGrafico.Add("Pie");
            ViewBag.TiposGrafico = tiposGrafico;
            return View();
        }

        public PartialViewResult ConsultaGrafico(int idCategoria,string tipoGrafico)
        {
            brProducto obrProducto = new brProducto();
            List<beProducto> lbeProducto = obrProducto.listarPorCategoria(idCategoria);
            int ancho = 800;
            int alto = 500;
            Bitmap bmp = new Bitmap(ancho, alto);
            Graphics grafico = Graphics.FromImage(bmp);
            Rectangle rect = new Rectangle(0, 0, ancho, alto);
            LinearGradientBrush degradado = new LinearGradientBrush
            (rect, Color.Aqua, Color.Blue, LinearGradientMode.BackwardDiagonal);
            grafico.FillRectangle(degradado, rect);
            int x, y;
            Font fuente=new Font("Arial",10);
            Pen lapiz=new Pen(Brushes.Yellow,5);
            StringFormat formato = new StringFormat(StringFormatFlags.DirectionVertical);
            switch (tipoGrafico)
            {
                case "Barras":
                    x = 20;
                    y=20;
                    foreach(beProducto obeProducto in lbeProducto)
                    {
                        x = 20;
                        grafico.DrawString(obeProducto.Nombre, fuente, 
                        Brushes.White, x, y);
                        x = 200;
                        rect = new Rectangle(x, y, obeProducto.Stock, 20);
                        grafico.FillRectangle(Brushes.Yellow, rect);
                        x = 220 + obeProducto.Stock;
                        grafico.DrawString(obeProducto.Stock.ToString(), fuente, 
                        Brushes.White, x, y);
                        y += (int)fuente.GetHeight() + 20;
                    }
                    break;
                case "Columnas":
                    x = 20;
                    y=350;
                    foreach(beProducto obeProducto in lbeProducto)
                    {
                        grafico.DrawString(obeProducto.Nombre, fuente, 
                        Brushes.White, x, y, formato);
                        alto = 340 - obeProducto.Stock;
                        rect = new Rectangle(x, alto, 20, obeProducto.Stock);
                        grafico.FillRectangle(Brushes.Yellow, rect);
                        grafico.DrawString(obeProducto.Stock.ToString(), fuente, 
                        Brushes.White, x, alto - 20);
                        x += 50;
                    }
                    break;
                case "Lineas":
                    x = 20;
                    y=350;
                    for(int i=0;i<lbeProducto.Count;i++)
                    {
                        grafico.DrawString(lbeProducto[i].Nombre, fuente, 
                        Brushes.White, x, y, formato);
                        if (i < lbeProducto.Count - 1)
                        {
                            grafico.DrawLine(lapiz, new Point(x, 340 - lbeProducto[i].Stock), 
                            new Point(x + 50, 340 - lbeProducto[i + 1].Stock));
                        }
                        grafico.DrawString(lbeProducto[i].Stock.ToString(), fuente, 
                        Brushes.White, x, 320 - lbeProducto[i].Stock);
                        x += 50;
                    }
                    break;
                case "Pie":
                    decimal total = lbeProducto.Sum(obj => obj.Stock);
                    float anguloInicio = 00.0F;
                    float anguloFin;
                    rect = new Rectangle(100, 10, ancho-200, alto - 20);
                    int R, G, B;
                    Color color;
                    Random oAzar = new Random();
                    for (int i = 0; i < lbeProducto.Count; i++)
                    {
                        R = oAzar.Next(255);
                        G = oAzar.Next(255);
                        B = oAzar.Next(255);
                        color = Color.FromArgb(R, G, B);
                        anguloFin = (float)((lbeProducto[i].Stock * 360) / total);
                        grafico.FillPie(new SolidBrush(color), rect, anguloInicio, anguloFin);
                        anguloInicio += anguloFin;
                    }
                    break;
            }
            byte[] imagen=null;
            using (MemoryStream ms = new MemoryStream())
            {
                bmp.Save(ms, ImageFormat.Png);
                imagen = ms.ToArray();
            }
            ViewBag.Imagen = String.Format("data:image/png;base64,{0}",
            Convert.ToBase64String(imagen));
            return PartialView("Grafico", lbeProducto);
        }
    }
}

Nota: Para el gráfico de Pie se esta creando un color al azar para cada producto.

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:gray;
}
.Titulo {
    background-color:black;
    color:white;
    font-size:larger;
}
.Subtitulo {
    background-color:white;
    color:black;
    font-size:large;
}
.AnchoTotal {
    width:100%;
}
.Centrado {
    text-align:center;
}
.FilaCabecera {
    background-color:lightgray;
    color:black;
}
.FilaDatos {
    background-color:white;
    color:black;
}

Crear la Vista Productos para mostrar los datos

Ir al controlador y ubicarse sobre el método "Lista" (acción), clic derecho y seleccionar "Agregar vista", desmarcar todos los check ya que es una vista sin tipo y 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" />
</head>
<body>
    <div>
        @using (Ajax.BeginForm("ConsultaGrafico", "Producto", 
         new AjaxOptions { HttpMethod = "get", InsertionMode = InsertionMode.Replace, 
         UpdateTargetId = "divGrafico" }, new { id = "frmGrafico" }))
        {
        <table class="AnchoTotal">
            <tr class="Titulo">
                <td colspan="2">Gráficar Datos en el Servidor en ASP.NET MVC 
                 con llamada asíncrona usando Ajax Form y Vista Parcial</td>
            </tr>
            <tr class="Subtitulo">
                <td colspan="2">Consulta de Productos por Categoría</td>
            </tr>
            <tr>
                <td style="width:40%">Seleccione la Categoría</td>
                <td style="width:60%">Seleccione el Tipo de Gráfico</td>
            </tr>
            <tr>
                <td>
                    @Html.DropDownList("idCategoria",
                     new SelectList(ViewBag.Categorias,"IdCategoria","Nombre"))
                </td>
                <td>
                    @Html.DropDownList("tipoGrafico",
                     new SelectList(ViewBag.TiposGrafico))
                </td>
            </tr>
            <tr>
                <td colspan="2">
                    <div id="divGrafico"></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>iniciarLista();</script>
</body>
</html>

Nota: Es mejor colocar los archivos de JavaScript al final de la página para renderizar mas rápido.

Crear la Vista Parcial con la Consulta y el Gráfico a Mostrar

Ir nuevamente al controlador y ubicarse sobre el método "Lista" (acción), clic derecho y seleccionar "Agregar vista", cambiar de nombre a la vista por "Grafico", seleccionar el check "Crear como vista parcial" y escribir el siguiente código:

@using Northwind.Librerias.EntidadesNegocio
@model List<beProducto>
<table class="AnchoTotal">
    <tr>
        <td style="vertical-align:top">
            <table class="AnchoTotal">
                <tr class="FilaCabecera">
                    <td style="width:200px">Nombre del Producto</td>
                    <td style="width:10px">Stock</td>
                </tr>
                @foreach (beProducto obeProducto in Model)
                {
                    <tr class="FilaDatos">
                        <td>@obeProducto.Nombre</td>
                        <td>@obeProducto.Stock</td>
                    </tr>
                }
            </table>
        </td>
        <td>
            <img src="@ViewBag.Imagen" width="800" height="500" />
        </td>
    </tr>
</table>

Crear el archivo JavaScript con el código cliente

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

function iniciarLista() {
    $("#frmGrafico").submit();
    var cboIdCategoria = document.getElementById("idCategoria");
    cboIdCategoria.onchange = function () { llamadaAsincrona(); };
    var cboTipoGrafico = document.getElementById("tipoGrafico");
    cboTipoGrafico.onchange = function () { llamadaAsincrona(); };
    function llamadaAsincrona() {
        $("#frmGrafico").submit();
    }
}

Nota: Cuando se carga la página se esta haciendo un submit al formulario "frmGrafico" via jQuery el cual es asíncrono por que el formulario en un Ajax Form. También ocurre lo mismo al seleccionar una categoría del combo.

Modificar el archivo web.config para incluir la cadena de conexión

<configuration>
  <connectionStrings>
    <add name="conNW" providerName="SQLServer"
         connectionString="uid=UsuarioNW;pwd=123456;
         data source=DSOFT\Sqlexpress;database=Northwind"/>
  </connectionStrings>
  .....
</configuration>

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 sigue: controller = "Producto", action = "Lista".

Ejecución y Pruebas de la Aplicación Web ASP.NET MVC

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


Por defecto se muestra la categoría "Bebidas" y en el tipo de gráfico "Barras", cambiar el tipo de gráfico a "Columnas" y se verá la siguiente figura:


Probar ahora con el gráfico de "Lineas" y se mostrará algo similar a la siguiente figura:


Finalmente, cambiar el tipo de gráfico a "Pie" y se verá lo siguiente:


Nota: En el gráfico de Pie falta agregar una leyenda para distinguir cada producto de acuerdo al color generado. Esto queda como tarea para que aprendan mas sobre Drawing.

Comentario Final

En este post hemos visto como trabajar en forma conectada, y también hemos aprendido a crear gráficos dinámicamente usando la librería System.Drawing y las clases: Bitmap, Graphics, Rectangle, Font, Pen, StringFormat, Color, SolidBrush, las enumeraciones: Brushes y StringFormatFlags, también el Namespace: System.Drawing.Drawing2D para usar la clase: LinearGradientBrush (degradado).

En un anterior post vimos como crear gráficos en el Cliente usando HTML5 Canvas con JSON:

Aunque en apariencia los Demos son similares el anterior es desconectado de la base de datos y del servidor web, este demo es conectado o en línea para ver los últimos datos, por ejemplo muy útil para reportes gerenciales en línea.

Descarga del código

Video del Demo

Nota: El video es muy similar al código presentado en el Demo, pero la versión original era desconectada del servidor de datos y usaba una sesión, en cambio el demo es totalmente conectado, la diferencia solo es en el controller y es mínima.