ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA Walter Montes Delgado ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA Walter Montes Delgado ©2015 Walter Montes Delgado ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 2 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 3 Tabla de Contenidos ACERCA DEL AUTOR ............................................................. 4 REGISTRO DE CAMBIOS........................................................ 5 INTRODUCCIÓN PERSONAL - PORQUÉ UNA GUÍA INTRODUCTORIA A MVC ...................................................... 7 CAPÍTULO UNO – UNA INTRODUCCIÓN A .NET 2015 Y ASP.NET 5 ................................................................................. 9 CAPÍTULO DOS – EL PATRÓN QUE TODOS AMAN, MVC .................................................................................................. 12 CAPÍTULO TRES – ASP.NET MVC 6 SIN PERDERSE ....... 14 Una pequeña introducción al desarrollo web ........................ 14 ASP.NET MVC 6 ................................................................. 15 VISTAS ................................................................................ 27 CONTROLADORES............................................................ 31 MODELOS ........................................................................... 35 EJERCICIOS ........................................................................ 35 Agregar una nueva vista .................................................... 35 Comunicación cliente hacia servidor ................................ 37 CAPÍTULO CUATRO – CARACTERÍSTICAS AVANZADAS .................................................................................................. 41 Pase de información entre el controlador y la vista ............... 41 Validaciones ......................................................................... 46 Vistas parciales vs ViewComponents (VCs) ......................... 52 Agregando una base de datos ................................................ 58 Usando Dependency Injection .............................................. 65 CONCLUSIÓN......................................................................... 68 ACERCA DEL AUTOR Walter Montes tiene múltiples años trabajando con tecnología Microsoft desde desarrollo de software, instalación y configuración de productos hasta arquitectura de soluciones. Al momento de escribir este libro, es el único Microsoft Most Valuable Professional (MVP) en ASP.NET/IIS de Centroamérica. Además de ser el administrador de la comunidad oficial de desarrolladores .NET en Costa Rica CR Developers .NET. Cuenta con su propio blog en tecnología Microsoft y Open Source en la siguiente dirección: http://waltermontes.com ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 4 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 5 REGISTRO DE CAMBIOS Esta es la segunda versión de este libro, la cual incluye arreglos, comentarios extra y todo lo liberado de manera oficial en Visual Studio 2015 RTM para MVC 6. Trataré de enumerar la mayoría de cambios “impactantes” en esta sección para que si ya leíste la versión 1, puedas enfocarte solamente en lo nuevo. Si lees este libro por primera vez puedes ignorar esta sección y pasar al siguiente capítulo. Gracias especiales a todas las personas que leyeron la primera versión de este libro, se suscribieron e inclusive enviaron agradecimientos y retroalimentación. Ya que al día de hoy el libro tiene más de 615 descargas y más de 120 suscriptores. Lo interesante es que actualmente el cambio entre una versión Release Candidate (RC) – versión con la cual liberé la primera versión de este libro – y la versión Release to Manufacturing (RTM) – versión con la cual libero esta segunda versión – no varían demasiado entre sí, ya que Microsoft ha sido muy abierto durante el proceso de desarrollo y liberado anticipadamente cada nueva característica. Cambios: Cambio de formato o Decidí transcribir el libro a un documento PDF regular. Inicialmente así comencé a escribirlo y casi lo terminé, sin embargo me recomendaron transcribirlo a un formato más compatible con múltiples dispositivos de manera “nativa” por eso opté por utilizar el editor en línea de leanpub, sin embargo el formato de markdown que utiliza no es muy flexible y el editor tiene ciertos problemas que me inclinaron a volver a un formato más de PDF normal. A partir de la sección ASP.NET MVC 6 he actualizado las imágenes para que calcen con lo que se encontrarán en Visual Studio 2015 RTM. Mayor detalle con respecto a GULP, qué es y para qué sirve en la sección ASP.NET MVC 6. Mayor detalle con respecto a Dependency Injection, qué es y para qué sirve en la sección ASP.NET MVC 6. Mayor detalle en los ejemplos. Mayor detalle con respecto a Entity Framework, qué es y para qué sirve en la sección Agregando una base de datos. Un ejemplo de cómo utilizar el contenedor de Dependency Injection que viene por defecto en ASP.NET 5 en la sección Usando Dependency Injection. Carga del ejemplo a mi cuenta de GitHub para que puedan descargarla: https://github.com/walmon/MVC6UNAGUIAINTROD UCTORIA ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 6 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 7 INTRODUCCIÓN PERSONAL PORQUÉ UNA GUÍA INTRODUCTORIA A MVC Para nadie es un secreto que .NET Framework de Microsoft es una plataforma lo suficientemente robusta como para soportar millones de aplicaciones críticas en las organizaciones, que además estará con nosotros por muchísimos años en el futuro. Con el crecimiento de la internet, Microsoft ha escuchado a los desarrolladores, empresas y emprendedores, a raíz de esto ha orientado el desarrollo de su Framework hacia algo que hoy en día con .NET 2015 es una plataforma de desarrollo abierta, inclusiva y multiplataforma. Sumado a todo esto que se ha ido viendo en los últimos años con la plataforma de Microsoft, está la orientación de ASP.NET hacia el software abierto y a cumplir y trabajar agradablemente con estándares mundiales que otras plataformas implementan. Prueba de esto fue el nacimiento de ASP.NET MVC, el cual le permite a los desarrolladores poder separar mejor las responsabilidades de un sistema, conocer completamente el markup de su aplicación y a entender como es la comunicación entre el cliente y el servidor, permitiendo optimizar sus sistemas. Es por esto que he tomado la decisión de aportar a la comunidad hispana con un libro sencillo y al grano de ASP.NET MVC 6, para ayudarles a esas personas que apenas están entrando al mundo de MVC a entender este patrón y que las personas que ya lo conocen que puedan validar fundamentos básicos mientras logran adentrarse un poco más. Previo a iniciar a leer este libro sería ideal que ya conozca las siguientes tecnologías al menos a un nivel básico: C# HTML CSS JavaScript Todo lo presentado en este libro representa mi punto de vista personal y no busca representar a ningún empleador ni a Microsoft como corporación. ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 8 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 9 CAPÍTULO UNO – UNA INTRODUCCIÓN A .NET 2015 Y ASP.NET 5 Antes de entrar en materia, es importante entender los cambios que .NET Framework está teniendo para conocer cómo impacta esto a ASP.NET. Probablemente mucha de la información que será presentada a continuación pueda ser confusa si estás empezando en .NET o ASP.NET, así que el consejo sería que más adelante vuelvas a esta sección y le des otra leída posterior a finalizar el libro. .NET 2015 es el nombre que se le da a la nueva versión de .NET Framework y un buen punto de arranque es ver un diagrama como Microsoft presenta esta nueva versión liberada. Vista de alto nivel de .NET 2015 Durante este libro se tomará un enfoque principalmente en a donde está ubicado ASP.NET dentro de esta “sombrilla” pero igualmente les insto a conocer todo el mapa de .NET Framework y en mi parecer personal, principalmente sobre C# 6, Roslyn, CoreCLR y .NET Native. Lo más notorio de este diagrama es la separación de .NET Framework en dos bloques: .NET Framework 4.6 y .NET Core 5. .NET Framework 4.6: Continúa el trabajo que trae .NET 4.5.2 con muchísimas mejoras alrededor del framework. Se puede ubicar como el framework que viene incluido en el sistema operativo, en este caso en Windows 10 y el cual recibe actualizaciones a través del conocido Windows Update. Es importante notar que sobre .NET Framework 4.6 están las tecnologías WPF, Windows Forms y ASP.NET versiones 4 y 5. .NET Core 5: Microsoft lo describe como un “framework modular”, el cual llega a nosotros como una versión de software abierto, el cual puede ser desplegado de manera modular y local, además de ser mucho más ligero. Al ser modular busca también ser multiplataforma, corriendo en Windows, Linux y OSX. A diferencia de .NET Framework 4.6, .NET Core 5 permite correr aplicaciones ASP.NET solamente en la versión 5 y Universal Windows Apps con .NET Native. De esta forma ASP.NET se ubica de la siguiente manera dentro del universo .NET. Donde está ASP.NET 5 en el universo .NET Con ASP.NET 5 corriendo en ambas “ediciones” del framework se logra desplegar y desarrollar aplicaciones web tanto en Windows (sobre .NET Framework 4.6 o corriendo lado a lado sobre .NET Core 5 con otra versión de .NET Framework instalada en el servidor) como en Linux y OSX. ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 10 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 11 A este punto .NET Core 5 soporta solamente ASP.NET MVC en C#, es decir, no Web Forms ni VB.NET. Esto no significa que no pueda ser que Microsoft incluya soporte a Web Forms o VB.NET en el futuro. Por otro lado .NET Framework 4.6 si continúa soportando el modelo de desarrollo en Web Forms y el lenguaje de programación VB.NET. Algunas de las características más notables de ASP.NET 5 es la unificación de MVC, Web API y Web Pages en un solo modelo conocido como MVC 6. Otra importante adición es la integración con herramientas populares de desarrollo web como Bower, Grunt y Gulp, los cuales ya se podían utilizar con otros frameworks de desarrollo como PHP, Node.JS y Ruby. CAPÍTULO DOS – EL PATRÓN QUE TODOS AMAN, MVC Modelo Vista Controlador, es lo que las siglas MVC representan, y su objetivo principal es lograr la separación entre estos tres “personajes”, lo cual permite, a través de este patrón de diseño, crear aplicaciones robustas tomando en consideración buenas prácticas aprendidas de otras plataformas de desarrollo y del propio Microsoft. Modelo Vista Controlador La separación de conceptos busca precisamente que cada “bloque” de la aplicación realice solo el trabajo que le corresponde, así logra obtener otras ventajas tales como mantenibilidad del sistema, extensibilidad y crecimiento ordenado. Así como otros patrones ya buscan logra esto, tales como programación en N-Capas, MVC puede seguir estos lineamientos como separación de proyectos para distribuir componentes ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 12 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 13 comunes. Todo esto es porque MVC como tal es un patrón, no una tecnología. Vista: La vista es el conjunto de markup de la aplicación, es decir el HTML. En ASP.NET MVC este markup es pre renderizado a través de una tecnología llamada Razor, la cual permite, entre otras cosas, ejecutar lógica previa a renderizar el HTML que será enviado al cliente. Con Razor esta compilación o renderización ocurre del lado servidor. No debería incluir ningún tipo de lógica de negocio, sino más bien lógica propia de interacción con el usuario, como iterar una lista (List) y presentar una lista ordenada (ul) de ítems al usuario. Modelo: Son los objetos de dominio o negocio de la aplicación, más adelante, veremos que no es necesario que esté en el mismo proyecto que la aplicación web. Controlador: El controlador se encarga de recibir solicitudes y ser el punto de entrada de la aplicación, a través de lo que se conoce como acciones (Actions). Se basa en solicitudes HTTP y puede responder con datos o con contenido, como HTML. CAPÍTULO TRES – ASP.NET MVC 6 SIN PERDERSE Una pequeña introducción al desarrollo web Esta sección es una introducción básica y esencial de desarrollo web, si ya estás familiarizado con desarrollo web en otras tecnologías, probablemente no sea necesario que pases por esta sección. En el desarrollo web, se trabaja con un servidor que responde archivos e información y un navegador que ejecuta y lee los archivos. Por ejemplo: El cliente inicia una solicitud por HTTP al servidor, por ejemplo http://www.bing.com, y el servidor, a través de ASP.NET procesa la solicitud, contacta bases de datos y demás, y retorna páginas HTML renderizadas, archivos CSS, JavaScript y medios (imágenes, videos, etc). HTML: markup de la página JavaScript: lógica de lado cliente (pc de usuario) CSS: hojas de estilo La comunicación entre el cliente y el servidor se realiza a través de HTTP por lo que cada solicitud se conforma de una solicitud ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 14 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 15 (request) y una respuesta (response). Las solicitudes web tienen como mínimo un encabezado (header) y un cuerpo (body). El encabezado indica dirección de la solicitud, tipo de solicitud e información del contenido aceptado, entre otros; y el cuerpo incluye información que se envía al servidor. De esta forma el tipo de solicitud se define a través de un verbo HTTP que indica el tipo de solicitud, los principales verbos que se deben conocer son: GET: usualmente conocido como verbo “obtener”, no incluye cuerpo POST: solicitud de envío de información, debe ir acompañado de un cuerpo de contenido, por ejemplo una imagen o un JSON PUT: similar al POST, sin embargo se utiliza para cuando se realizan actualización de recursos DELETE: similar al en estructura al GET, pero el servidor debe entender que se busca remover el recurso que se consulta en lugar de retornarlo ASP.NET MVC 6 ¿Qué mejor forma de comenzar a aprender una tecnología que ir directo al código y explorarlo? Pues ese será el siguiente pasó en este libro. Durante todo el recorrido se irán mencionando algunos conceptos importantes y al final un par de ejemplos. Antes de comenzar, es importante entender que una plantilla de Visual Studio, no es más que una serie de DLLs que funcionan para un fin específico incluidas en un proyecto + una base de código configurativa de la tecnología + uno o varios ejemplos de código. Es decir, si uno quisiera hasta podría empezar un proyecto sin necesidad de seleccionar un template de Visual Studio. La forma de “unificar” archivos en forma de proyecto es a través de archivos con extensión .csproj o .vbproj, los cuales a su vez se pueden agrupar en una solución con archivos extensión .sln. Para entender un poco más de archivos de proyecto y su funcionalidad. Estructura de solución Archivos no específicos de usuario: archivos propios del software, que pueden ser controlados por un manejador de versiones tal como TFS o Github. -sln .csproj o .vbproj Archivos específicos de usuario: archivos propios el software desarrollado para el usuario de sistema actual. No son controlados por controladores de versiones. -suo .csproj.user o .vbproj.user Volviendo al tema de ASP.NET MVC el proceso de creación de un proyecto basado en una plantilla es sencillo, en Visual Studio > File/Archivo > New/Nuevo> Project/Proyecto ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 16 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 17 Nuevo Proyecto El siguiente paso es seleccionar la plantilla de MVC 6, debe fijarse que seleccione .NET Framework 4.6 y colocar un nombre de proyecto y de solución acorde a sus necesidades ya que este será el nombre de espacio que seguirá su proyecto (orden interno del proyecto). Usualmente y por estándar de Microsoft se nombra el nombre de espacio de la siguiente forma Definición de la plantila MVC 6 Para los que vienen desde versiones anteriores previo a Visual Studio 2012, ha visto un par de cosas nuevas, entre ellas, que no tuvieron que seleccionar el tipo de proyecto (Web Forms, MVC o Web Pages), sino que se selecciona un proyecto de tipo ASP.NET, esto es por un cambio que se dio en el 2013, en el cual aparece el término ONE ASP.NET, el cual busca que se puedan crear proyectos con tecnología Web Forms y MVC/Web API en un solo proyecto de Visual Studio, a diferencia de como anteriormente solo se podía seleccionar un tipo. La siguiente pantalla que aparece a continuación da la opción de seleccionar una nueva plantilla de proyecto ASP.NET 5. En este caso se debe seleccionar Web Site, el cual crea una plantilla para un sitio web MVC y Web API. ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 18 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 19 Tipo de Proyecto ASP.NET En la imagen anterior se ha resaltado la opción “Change Authentication” para dar un poco de énfasis a esta opción. Si se le da clic a este botón, aparece la siguiente pantalla. Cambiar autenticación Esta ventana da la opción de seleccionar la estrategia de autenticación, por lo cual se debe tener de antemano una idea de la estrategia de autenticación y autorización del sistema. Esto porque más adelante se puede cambiar, sin embargo puede ser un poco complicado si no se conoce bien a detalle cómo se implementa cada modelo, ya que al seleccionar una opción se crean las clases y configuraciones de ASP.NET y/o IIS para procesar un modelo de autenticación. ¿Cómo determinar el modelo de autenticación? No Authentication: en caso de que no se requiera autenticación o se desee implementar un tipo especial de autenticación Individual User Accounts: en caso de que se quiera contar con usuarios propios para el sistema, es decir, con una base de datos SQL Server que almacene usuarios y contraseñas de manera segura y con buenas prácticas, y/o cuando se quiere autenticar usuarios con una tercera parte, tal como Facebook, Twitter, Google o Microsoft. Work And School Accounts: permite autenticar con proveedores de autenticación empresiales, tal como Azure Active Directory o Active Directory Federation Services. Windows Authentication: en ambientes corporativos cuando las computadoras clientes están en un dominio en Active Directory Domain Services, de esta forma no se ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 20 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 21 solicita al usuario autenticarse, sino que se utilizan los credenciales de Windows. Para la demostración se va a dejar marcada la opción de Individual User Accounts, el cual utiliza el Simple Membership Provider para obtener autenticación de usuarios en una base de datos SQL Server en LocalDB (más adelante se ahondará un poco más en este tema). Al terminarse de aprovisionar el proyecto es probable que el nodo “References” aparezca de esta forma References (Restoring) por unos segundos mientras se terminan de descargar y aprovisionar las DLLs necesarias. Al finalizar se deberá ver una estructura de folders y archivos similar a la de la imagen de la derecha. En esta nueva versión de .NET y Visual Studio, NuGet toma mucho protagonismo, ya que se busca que con .NET Core solo se traiga lo mínimo necesario y lo demás que se ocupe sea descargado a través de NuGet. Esta nueva estructura es muy similar a las de los proyectos en Github o Codeplex. Estructura Proyecto Los primeros niveles son: Solutions Items src El primer archivo global.json dentro del folder Solution Items es el archivo que contiene la información del proyecto para Visual Studio u otras herramientas, en este caso el archivo está casi vacío, solo contiene información de las carpetas y versión del SDK. Para los que vienen de versiones anteriores de .NET ver archivos configurativos con extensión JSON es algo totalmente nuevo, por otro lado para los que vienen de otras plataformas como Node.JS es algo muy común y natural. Archivo global.json En el siguiente folder src donde se ven los archivos propios del proyecto, como ya se han conocido anteriormente. Dentro del folder src parecen los proyectos de la solución, en este ejemplo solo existe el proyecto de Interfaz de Usuario “wm.website.ui”. En este nuevo proyecto de MVC 6 aparece un folder llamado wwwroot (nuevo en esta versión), el cual contiene archivos que no deben ser compilados, tales como hojas de estilo (CSS), imágenes y archivos de JavaScript. ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 22 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 23 Folder wwwroot A nivel de raíz de proyecto hay otros archivos extensión .json, tales como bower.json, config.json, package.json y project.json. ¡Sí! No hay web.config por defecto, sin embargo ASP.NET 5 soporta archivos configurativos en formato XML, INI o JSON. Para tratar de entender todo este cambio configurativo se hará un pequeño overview de cada archivo. bower.json El archivo bower.json, contiene, como su nombre lo dice, configuraciones propias de bower. ¿Qué es bower? Bower, al igual que NPM son administradores de paquetes, algo así como NuGet pero se comparten entre diferentes tecnologías ya que usualmente no dependen de la tecnología backend. En este caso Bower permite manejar dependencias de lado cliente, tales como jquery, bootstrap, etc. config.json, package.json y project.json Entre estos archivos prácticamente se distribuyen las configuraciones que anteriormente existían en el archivo web.config. Si eres nuevo en desarrollo web sobre .NET, el web.config era un archivo XML que contenía configuraciones propias del proyecto. Durante este libro no se va a ahondar tantísimo en cada detalle nuevo, más bien, se intentará que sea algo más funcional y directo a entender lo mínimo necesario de ASP.NET 5. El archivo Startup.cs es el que invoca los .json e inyecta dependencias necesarias (más adelante se conversará un poco más al respecto). Gulp El desarrollo web moderno utiliza herramientas que permiten crear mejores aplicaciones (más veloces, optimizadas y seguras). Anteriomente se mencionaron Grunt y Gulp por encima, voy a tratar de ahondar un poco más en Gulp que es el task runner incluido por defecto. Un task runner es permite automatizar un flujo de desarrollo web para crear N cantidad de tareas a ejecutarse en diversos puntos de ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 24 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 25 la compilación, tales como procesar archivos de LESS o SAAS (preprocesadores de estilos que permiten estructurar mejor los estilos de un sitio, utilizar variables para tener un código más mantenible, incrustar lógica, entre muchas otras opciones) y convertirlos en el CSS que el navegador entiende, procesar archivos de CoffeeScript o TypeScript y convertirlos en el JavaScript que el navegador entiende, minificar y ofuscar el código, correr librerías como JSLint (verifica buenas prácticas en el código JavaScript), entre muchísimas más cosas. Por ejemplo en este caso el archivo si abrimos el gulpfile.js vemos una serie de tareas como minificación y limpiado de archivos css y JavaScript. Dependency Injection El patrón Dependency Injection o Inyección de Dependencias existía en MVC, Web API y SignalR desde antes, sin embargo no de manera tan explícita ni tan consistente. Es por esto que ASP.NET 5 se unificó esta sección de manera más consistente. Dependency Injection permite acceder a servicios en diferentes puntos de la ejecución de un sistema, por ejemplo en controladores o apenas inicia la aplicación. Además trae un contenedor de Dependency Injection que permite consolidar el sistema y sus configuraciones. Más adelante mostraré un ejemplo de cómo utilizar Dependency Injection con la abstracción por defecto de ASP.NET 5, sin embargo esta puede ser reemplazada por otro contener como Ninject o Autofact. ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 26 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 27 Entrando ya en temática de propia ya de MVC, se pueden observar los folders Controllers, Views y Models. Para correr inicialmente la plantilla se debe presionar F5 y se podrá observar la nueva plantilla corriendo. Este template ya tiene incluidas las librerías jQuery y Bootstrap, además de otras más. Por lo cual ya trae un diseño inicial y unas páginas iniciales que responden solicitudes a través de controladores. Ejecución básica VISTAS Lo primero que se verá en esta línea serán las vistas y cómo funcionan entre sí. ¿Dónde están ubicadas? En el folder Views. ¿Qué extensiones tienen? .cshtml o .vbhtml dependiendo del lenguaje de programación, si es C# la extensión es cshtml, si es Visual Basic la extensión es vbhtml. ¿Qué lenguaje se utiliza? HTML a través del pre compilador de HTML llamado Razor. Todo website tiene ciertos componentes que se repiten entre páginas, tipo “marco”. En Web Forms se le conocía como MasterPage, en MVC se le conoce como _Layout. Usualmente estas secciones incluyen partes como encabezados, pie de página y menús de navegación. Por ejemplo en la imagen de la derecha lo que está en celeste sería el layout. Layout layout.cshtml Este archivo incluye todo el marco y plantilla HTML, es decir, tags como <head>, Al abrir este archivo se puede apreciar algo nuevo en esta versión de ASP.NET, el tag “environment” el cual permite, según el despliegue que se realice, agregar unos u otros archivos de scripts y hojas de estilos. Por ejemplo para el momento de desarrollo sirven los archivos fuentes iniciales, sin embargo en producción usualmente los archivos que se envían a un usuario son los archivos de hojas de estilo y scripts minificados y obfuscados. Esto para evitar el uso innecesario de ancho de banda y complicar la lectura del código fuente que se descarga del lado cliente y que durante desarrollo se pueda realizar depuración de código JavaScript. ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 28 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 29 Etiqueta Environment Al investigar un poco más el archivo se puede encontrar la sentencia @RenderBody() en esta parte del HTML se renderizará el resto de páginas que utilicen este archivo de layout. La manera de asignar este layout a diferentes páginas es a través de una variable llamada Layout. Es decir si en alguna vista se asigna algún valor a esa variable global, esa página utilizará ese archivo de layout. Con el siguiente diagrama se intentará explicar un poco más claro esto. Renderización vista Como se pudo notar al ejecutar el proyecto, la página que fue retornada ya traía un layout y contenido renderizado, esto es porque por defecto cada vista creada tiene un layout por defecto. Esta configuración se realiza en el archivo _ViewStart.cshtml. Es decir, si no se indica explícitamente en cada vista cual archivo de layout utilizar, la vista utilizará el que se indique en el archivo _ViewStart.cshtml Asignación Layout La sentencia anterior definida por @{ } Permite incrustar código C#, se conocen como bloques de código (code blocks) y permiten ejecutar lógica, por ejemplo: Bloque de código El símbolo @ también permite utilizar también lo que se conoce como Tag Helpers. Los cuales básicamente renderizán bloques de HTML basándose en cierta lógica, fuera de caja se incluyen los conocidos como HTML Helpers. Existen diferentes Tag helpers que se pueden utilizar por ejemplo optar por el que ha venido desde versiones anteriores: ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 30 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 31 HTML Helper O utilizar uno de los nuevos tag helpers que permite un código más “limpio” al utilizar atributos de HTML. Por ejemplo: Nuevo Tag Helpers Al fin y al cabo ambos renderizan al final el siguiente bloque de código HTML: <a href="/Account/Login">Click here to Log in</a>. Vistas de contenido Las vistas contienen el HTML base + lo renderizado por el Razor. Su contenido dependerá de la información que se desea mostrar, más adelante se mostrará cómo se asocia con un controlador y con un modelo. CONTROLADORES Un controlador se conforma de una clase con funciones que responden solicitudes HTTP. La clase equivale al nombre del controlador y la función equivale al nombre de la acción. Nombre de Clase = Controlador Nombre de Función = Acción Por ejemplo en el archivo Controllers/HomeController Clase de controlador De esa manera, se crea un extremo (endpoint web) que puede ser consultado a través de un cliente que pueda realizar solicitudes HTTP (un navegador, un robot, un dispositivo). Por ejemplo según la imagen anterior en HomeController existen las siguientes 2 rutas que responden solicitudes, acorde a la siguiente convención http://localhost:<puerto>/<CONTROLADOR>/<ACCION> http://localhost:<puerto>/Home/Index http://localhost:<puerto>/Home/About (*) nota: La palabra “controller” en la clase es removida del nombre. Así las solicitudes web se resuelven de la siguiente forma: ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 32 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 33 Procesamiento solicitudes web Entra la solicitud iniciada desde el cliente (pc o dispositivo), el servidor busca que haya una ruta que responda a esa url y responde el acción que corresponde. Como pudieron notar al ejecutar este proyecto la url http://localhost:<puerto>/ respondió una página a pesar de que no se indicó explícitamente el Controlador ni la acción, esto es porque al definir la convención de ruta se especifican unos valores por defecto. De la siguiente forma: Si no se indica la acción que se busca alcanzar, se utiliza por defecto la que se llame Index Si no se indica el controlador que se busca alcanzar, se utiliza por defecto la que se llama Home Esto se define a través del archivo Startup.cs en el siguiente bloque de código: Plantilla de ruteo En esa sección de código se define la convención a seguir, es decir {controlador}/{acción}/{id opcional} El controlador en el tipo de función define qué tipo de dato se retornará al cliente. Por ejemplo en el homecontroller, todas las acciones responden un tipo de dato IActionResult, en este caso todas las funciones retornan un objeto de tipo View. Plantilla de ruteo La función View se puede colocar sin pasar parámetros por lo cual la función buscará una vista que esté en el folder Views/<Nombre de Controlador>/<Nombre de Acción>. En este caso retornará la vista que esté ubicada en Views/Home/About. Sin embargo también se puede indicar explícitamente el nombre de la vista que ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 34 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 35 se desea retornar. La función buscará un archivo con el nombre indicado en el parámetro en varios folders del proyecto, por ejemplo View("About") y al encontrar la vista, la retornará al cliente. A pesar de todo esto, en lugar de un View se pueden retornar cualquier tipo de datos que herede de IActionResult. Comentarios de código Existen 3 tipos de comentarios en Razor: Comentarios HTML, son retornados al cliente en el HTML o <!-- este es un comentario --> Comentarios internos, no son retornados al cliente o * @* este es un comentario *@ * Comentarios dentro de bloques de código, no son retornados al cliente HTML o @{ // este es un comentario } Es importante saber qué tipo de comentario utilizar, para evitar estar retornando al cliente comentarios internos. MODELOS Los modelos son clases que representan objetos de dominio y pueden ser utilizados por la lógica de negocio y acceso a datos para manipular información. Están ubicado en la plantilla en el folder Models. EJERCICIOS Agregar una nueva vista Para este ejercicio se necesitará una nueva vista que sea retornada al hacer una consulta HTTP a un url. 1. En el archivo Controllers/HomeController.cs crear una función que permita retornar una nueva vista public IActionResult VistaPersonalizada() { return View(); } 2. Posterior a crear el extremo que ya recibe las solicitudes web, se debe crear una vista que sea retornada por la función View. 3. Escribir algún contenido en la vista recién creada ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 36 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 37 4. Probar el código ejecutando el proyecto (F5) y navegando a la ruta: http://localhost:<puerto>/home/vistapersonalizada 5. Disfrutar el resultado Comunicación cliente hacia servidor Para este ejercicio se necesitará un formulario apuntando a través de un método de tipo post a una acción en Home y este retornará una vista. 1. En el archivo Views/Home/Index.cshtml agregar un formulario apuntando a una acción del controlador Home, al comienzo del archivo <form asp-controller="Home" asp-action="SubmitForm" method="post"> <div class="row"> <div class="form-group"> <input name="nombre" placeholder="Nombre" class="form-control" /> </div> <div class="form-group"> <input name="edad" placeholder="Edad" class="formcontrol" type="number" /> </div> <div class="form-group"> <button type="submit" class="btn btndefault">Submit</button> </div> </div> </form> 2. Crear la acción que responda a esta solicitud, en el archivo Controllers/HomeController.cs agregar una función como la siguiente [HttpPost] public IActionResult SubmitForm(string nombre, int edad) { var nombreRecibido = nombre; var edadRecibida = edad; return View("Index"); } 3. Crear un breakpoint en la línea de código de la función. ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 38 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 39 4. Ejecutar el código, ingresar datos y dar clic a submit. 5. Visual Studio detectará el Breakpoint y este permitirá ver si se pasaron correctamente los valores. ¿Qué se puede notar del ejercicio anterior? Los atributos personalizados asp-controller y aspaction, los cuales renderizan en el atributo action=”Home/SubmitForm” El uso del atributo name en los inputs para ser relacionado con los parámetros de la función, el cual permite realizar la “liga” entre los valores enviados por el formulario con los recibidos en la función. De esta forma si hay un input con el atributo name y la acción a la que se apunta recibe un parámetro con el mismo nombre al valor del atributo name, ASP.NET los relaciona y asigna el valor a la variable. El uso del atributo [HttpPost] en la función SubmitForm, el cual diferencia que esta acción responderá solo a solicitudes de tipo POST. o Si no se indica este atributo en la función, por defecto se creará la función respondiendo a solicitudes tipo GET. ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 40 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 41 CAPÍTULO CUATRO – CARACTERÍSTICAS AVANZADAS En el capítulo anterior se hizo un recorrido inicial por ciertas funcionalidades principales de ASP.NET MVC 6. En el cual se pudo conocer lo básico de cada componente y cómo lograr comunicación y empezar a extender el proyecto básico. Pase de información entre el controlador y la vista Para compartir información entre una acción y una vista existen diversas estrategias que se pueden utilizar, tales como: ViewData permite pasar datos entre un controlador y una vista, solo sobrevive durante el solicitud actual ViewBag es una propiedad dinámica que permite utilizar “dynamics” de C# 4.0, solo sobrevive durante la solicitud actual. Usualmente sirve para pasar datos sencillos. TempData permite pasar información entre solicitudes subsecuentes (por ejemplo redirección) Modelo este modo permite asignar a una vista un modelo específico y pasarla por parámetros al retornar la vista Esta sección busca explicar un poco más como utilizar Razor y hacer algunas cosas un poco más complejas tales como renderizar listas y pasar información por ViewBag. Adentrándonos a Razor, renderizar una lista. 1. Crear un controlador llamado ItemsController. 2. Crear un folder en la ruta Views/Items y una vista llamada Index dentro de ese folder. 3. Crear un modelo llamado Items con el siguiente contenido. Clic derecho en el folder Models > Add > New Item… ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 42 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 43 4. Y se debe agregar este contenido. public class Item { public int Id { get; set; } public string Nombre { get; set; } } 5. En el controlador Items en la acción Index se deben crear algunos ítems de prueba para luego renderizarlos en la vista, de la siguiente forma. Además debe agregar la referencia a la clase Item. List<Item> items = new List<Item>(){ new Item() { Id=1, Nombre="Item1" }, new Item() { Id=2, Nombre="Item2" }, new Item() { Id=3, Nombre="Item3" }}; Con el cursor sobre el texto “Item” que muestra el error presiona Ctrl+. para mostrar el menú de sugerencias. 6. Para renderizarlos en la vista Index, se debe pasar a través de parámetros de la sentencia View(), en el mismo archivo ItemsController, posterior a inicializar la lista. return View(items); 7. Cree una vista nueva en un folder en Views/Items llamada Index.cshtml. 8. A la vista (opcionalmente- y para este ejemplo) se le debe indicar que utilizará este tipo de modelo, para esto se usa la sentencia @model al comienzo del archivo de vista. En el archivo Views/Items/Index borre todo el contenido y agregue la siguiente línea de código. @model List<Item> 9. Lo siguiente sería iterar en la lista que está siendo retornada y renderizar uno a uno los ítems. Use el siguiente bloque de código para este fin. Como podrá ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 44 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 45 notar se utiliza el carácter @ para ejecutar lógica en el archivo Razor. <ul> @foreach(var item in Model) { <li>id: @item.Id nombre: @item.Nombre</li> } </ul> 10. Ahora ejecute la aplicación (F5) y vea el resultado en el navegador en la dirección http://localhost:<puerto>/Items/ 11. Pasar información por ViewBag 12. En el mismo controlador, agregue la siguiente línea de código dentro de la acción Index en cualquier parte antes de la sentencia View. ViewBag.Mensaje = "¡Este valor es pasado por ViewBag!"; 13. En la vista agregue un poco de markup para mostrar el valor en la vista de la siguiente forma. @model List<Item> <h1>@ViewBag.Mensaje</h1> <ul> @foreach(var item in Model) { <li>id: @item.Id nombre: @item.Nombre</li> } </ul> 14. Ahora ejecute la aplicación (F5) y vea el resultado en el navegador en la dirección http://localhost:<puerto>/Items/ Validaciones En un sistema robusto, debe existir validaciones de datos de lado cliente y de lado servidor, si bien estas se pueden crear manualmente, “uno a uno”, esta tarea puede ser un poco engorrosa y compleja de mantener. Para esto ASP.NET MVC cuenta con una librería llamada DataAnnotations la cual permite definir qué validaciones se necesitan en el formulario de lado servidor y a través de jQuery Validate validar lado cliente. Las dataannotations ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 46 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 47 están en el nombre de espacio System.ComponentModel.DataAnnotations y permiten no solo especificar cierta información de validación, sino también ciertos metadatos que Razor entenderá, como cual texto mostrar en el label. DataAnnotations 1. Vaya al archivo Models/Item.cs y reemplace el contenido de la clase por el siguiente. using System.ComponentModel.DataAnnotations; namespace <sunombredeespacio>.Models { public class Item { [Required(ErrorMessage = "El identificador del ítem es obligatorio")] public int Id { get; set; } [Required(ErrorMessage ="El nombre del ítem es obligatorio")] [Display(Name ="Nombre de ítem")] [MaxLength(10, ErrorMessage ="El nombre del ítem no debe superar los 10 caracteres")] public string Nombre { get; set; } } } 2. Nuevamente posicione el cursor sobre una línea que tenga un error y presione Ctrl+. De lo anterior se puede resaltar lo siguiente: La inclusión del nombre de espacio DataAnnotations. El atributo sobre las propiedades de clase Required el cual permite definir que sea un campo requerido, así jQuery validate podrá colocarlo como requerido. Incluye la propiedad ErrorMessage, el cual permite agregar un mensaje personalizado en caso de que no se cumpla la condición indicada. El atributo Display que permite cambiar la forma en que en un label se mostrará el nombre del campo. El atributo MaxLength es uno de muchos otros atributos que se pueden agregar a propiedades de clase para definir características. 3. Para poder probar una validación debe primero existir un formulario de ingreso de datos. Para esto cree dos acciones en el controlador ItemsController. Uno para retornar el HTML y otro para recibir el submit del formulario. De la siguiente manera. public IActionResult Crear() { return View(); } [HttpPost] [ValidateAntiForgeryToken] public IActionResult Crear(Item nuevoItem) { return View(nuevoItem); } De lo anterior se puede resaltar lo siguiente: ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 48 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 49 Dos acciones, una para retornar el formulario vacío y otro para recibir los datos del submit. El atributo [ValidateAntiForgeryToken] el cual permite evitar ataques de CSRF. Debería ser utilizado siempre en las solicitudes de tipo POST o PUT. Un retorno en el POST de la sentencia View() con el modelo que ingresó por la solicitud, es decir, se retorna el formulario con la información previamente ingresada. 4. Cree una vista en el folder /Views/Items llamada “Crear” 5. Agregar la información del formulario HTML @model Item <form asp-action="crear" asp-controller="item" method="post" asp-anti-forgery="true"> <div asp-validation-summary="ValidationSummary.All" class="text-danger"></div> <div class="form-group"> <label asp-for="Id"></label> <input asp-for="Id" class="form-control" /> <span asp-validation-for="Id" class="textdanger"></span> </div> <div class="form-group"> <label asp-for="Nombre"></label> <input asp-for="Nombre" class="form-control" /> <span asp-validation-for="Nombre" class="textdanger"></span> </div> <button type="submit" class="btn btndefault">Submit</button> </form> @section Scripts { @{await Html.RenderPartialAsync("_ValidationScriptsPartial"); } } De lo anterior se puede resaltar lo siguiente: El formulario con el asp-action y asp-controller como ya se mencionó anteriormente para indicar cual extremo contactar. El atributo asp-anti-forgery para que el formulario sea compatible con el atributo anteriormente agregado [ValidateAntiForgeryToken] y así evitar ataques de CSRF. Con respecto a la versión RTM ahora se utiliza un valor de asignación “true” o “false”. El @model asignado es de tipo Item, esto le da el contexto al formulario para saber que será un formulario para ese tipo de dato. El atributo asp-validationsummary="ValidationSummary.All" el cual si existen errores en el formulario generará un tipo resumen de todos los problemas. El atributo asp-for en labels e inputs, el cual extrae los metadatos agregados a través de las propiedades de clases y DataAnnotations y los renderiza, por ejemplo, asigna el tipo de dato del input, el label, y mensajes de error. La sección Scripts, que permite renderizar los scripts de jQuery Validate que interceptan un submit y validan de lado cliente un formulario. 6. Agregue un breakpoint en el action que recibe la solicitud, es decir, el que tiene le atributo HttpPost y corra el proyecto (F5). En el formulario, sin llenar ningún campo de clic en submit. ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 50 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 51 7. Ingrese valores que cumplan con las especificaciones de validación y realice el submit. Debería llegar al breakpoint con los datos ingresados. 8. Lo que se acaba de realizar es validación de lado cliente, la cual puede extenderse del lado servidor con la siguiente sentencia en la acción post del crear. Esto en caso de que alguien intente burlar nuestra seguridad modificando el JavaScript y HTML en el navegador del usuario. [HttpPost] [ValidateAntiForgeryToken] public IActionResult Crear(Item nuevoItem) { if (ModelState.IsValid) { // guardar en la base de datos return RedirectToAction("Index"); } return View(nuevoItem); } 9. La variable ModelState permite validar el estado de lo que se haya utilizado como contexto del formulario. Si los datos se ingresan correctamente, el ModelState.IsValid será true, de caso contrario será un false. Vistas parciales vs ViewComponents (VCs) Los VCs son muy similares a lo que en versiones anteriores se conocían como Vistas parciales, las cuales buscan renderizar pequeños bloques de HTML, sirve en casos en los que se requiera manipular pequeñas porciones de una página, por ejemplo con manejo asincrónico de una página. La principal diferencia es que un ViewComponent es mucho más poderoso que una Vista Parcial debido a las formas de manipular la comunicación. Ejemplo de Vista Parcial 1. Crear una vista en el folder Views/Shared que será invocada desde el _Layout.cshtml ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 52 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 53 2. Reemplace todo el contenido por el contenido a continuación (el css se agrega en el mismo archivo solamente por simplicidad, no es una buena práctica bajo ninguna razón) <div class="bannerNoticias"> <p>Noticias</p> <div class="noticias"> <h4>Costa Rica en el puesto #13 de FIFA</h4> <p>Est porta ac magna lundium? Amet eros. Lorem cum ut auctor vel integer mus tortor, adipiscing platea penatibus, in placerat, lectus adipiscing! Ultrices scelerisque adipiscing parturient!</p> </div> <div class="noticias"> <h4>Nuevo ASP.NET 5</h4> <p>Est porta ac magna lundium? Amet eros. Lorem cum ut auctor vel integer mus tortor, adipiscing platea penatibus, in placerat, lectus adipiscing! Ultrices scelerisque adipiscing parturient!</p> </div> <div class="noticias"> <h4>¡Hololens está aquí!</h4> <p>Est porta ac magna lundium? Amet eros. Lorem cum ut auctor vel integer mus tortor, adipiscing platea penatibus, in placerat, lectus adipiscing! Ultrices scelerisque adipiscing parturient!</p> </div> <div class="clearer"></div> </div> <style> .bannerNoticias { border:solid 1px #aaa; border-radius:10px; padding:12px; } .bannerNoticias .noticias { display:inline-block; float:left; max-width:200px; font-size:12px; } .clearer{ clear:both; } </style> 3. En el archivo de Layout, inserte la siguiente línea de código debajo de la sentencia @RenderBody @RenderBody() @await Html.PartialAsync("_bannerNoticias") 4. Ejecute el proyecto (F5) y podrá apreciar una Vista parcial incrustada en cada página del sitio. ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 54 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 55 Ejemplo de ViewComponent En este caso crearemos un viewcomponent que logre lo mismo que la vista parcial anterior, sin embargo esta vez obtendremos las noticias desde el código, lo que más adelante podría ser reemplazado por datos desde una base de datos. 1. Crear un folder llamado ViewComponents en la raíz del proyecto. 2. Cree una clase llamada BannerInteractivoViewComponent.cs 3. Reemplace el contenido de la clase por el siguiente. using Microsoft.AspNet.Mvc; using System.Collections.Generic; using System.Linq; namespace <sunombredeespacio>.ViewComponents { public class BannerInteractivoViewComponent : ViewComponent { Dictionary<string, string> noticias = new Dictionary<string, string>(); public IViewComponentResult Invoke() { noticias = new Dictionary<string, string>() { { "Costa Rica en el puesto #13 de FIFA","Est porta ac magna lundium? Amet eros. Lorem cum ut auctor vel integer mus tortor, adipiscing platea penatibus, in placerat, lectus adipiscing! Ultrices scelerisque adipiscing parturient!"}, { "Nuevo ASP.NET 5","Est porta ac magna lundium? Amet eros. Lorem cum ut auctor vel integer mus tortor, adipiscing platea penatibus, in placerat, lectus adipiscing! Ultrices scelerisque adipiscing parturient!"}, { "¡Hololens está aquí!","Est porta ac magna lundium? Amet eros. Lorem cum ut auctor vel integer mus tortor, adipiscing platea penatibus, in placerat, lectus adipiscing! Ultrices scelerisque adipiscing parturient!"} }; return View(noticias); } } } 4. Ahora, cree un folder en la dirección Views/Shared/Components y dentro de ese folder, cree otro llamado BannerInteractivo (Views/Shared/Components/BannerInteractivo) y luego cree una vista que se llame Default.cshtml, agrege el siguiente contenido a la vista (el css se agrega en el mismo archivo solamente por simplicidad, no es una buena práctica bajo ninguna razón). @model Dictionary<string, string> <h2>¡Esto podría venir de una base de datos!</h2> ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 56 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 57 <div class="bannerNoticias"> <p>Noticias</p> @foreach (var item in Model) { <div class="noticias"> <h4>@item.Key</h4> <p>@item.Value</p> </div> } <div class="clearer"></div> </div> <style> .bannerNoticias { border: solid 1px #aaa; border-radius: 10px; padding: 12px; } .bannerNoticias .noticias { display: inline-block; float: left; max-width: 200px; font-size: 12px; } .clearer { clear: both; } </style> 5. En el _layout.cshtml agregue la siguiente línea debajo del @await Html.PartialAsync(“_bannerNoticias”) agregado previamente, esto para invocar nuestro ViewComponent. @Component.Invoke("BannerInteractivo") 6. Si ejecuta el proyecto (F5) verá el mismo resultado 2 veces, sin embargo con el ViewComponent podrá sacar los datos desde una base de datos más adelante, e inclusive ejecutarlo de manera asincrónica. Agregando una base de datos Para esto utilizaremos Entity Framework. Entity Framework es el principal ORM (object relational mapping) de Microsoft. El cual permite facilitar la comunicación y traducción de información entre una base de datos y un modelo de objetos. Por ejemplo, evitar tener que escribir las sentencias Insert, Delete, Update, List en T-SQL y orientarse más en la lógica que en cómo acceder los datos de la base de datos. Las principales modalidades de Entity Framework son Code First y Database First. La modalidad Code First permite escribir las clases (entidades) en C# o VB.NET y Entity Framework solo se encarga de crear las tablas en la base de datos y los accesos a datos. La modalidad Database First permite escribir primero las tablas en SQL Server y que Entity Framework extraiga la información y genere las clases en C# o VB.NET. Entity Framework (EF) extrae del archivo configurativo (config.json) los datos de conexión a la base de datos. Para este ejemplo utilizaremos Entity Framework Code First, el cual también crea la base de datos automáticamente. Ahora, vamos a utilizar el mismo ViewComponent, pero trataremos de obtener la información de las noticias desde la base de datos. Debido a esto, usaremos la instancia de LocalDB existente o cualquier instancia de base de datos instalada. ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 58 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 59 1. Crearemos una entidad de noticia para este ejemplo. En Models cree una clase que se llame Noticia.cs, reemplace el contenido con el siguiente. using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace <sunombredeespacio>.ui.Models { public class Noticia { public int Id { get; set; } public string Titulo { get; set; } public string Descripcion { get; set; } } } 2. Entity Framework ya está agregado al proyecto ya que decidimos habilitar autenticación de usuarios individual la cual utiliza una base de datos e implementa Entity Framework Code First. 3. Vamos a proceder a agregar el contexto de Code First. En el mismo folder de Models, cree un archivo que se llame NoticiasAppContext.cs y reemplace el contenido con el siguiente. using Microsoft.Data.Entity; namespace wm.website.ui.Models { public class NoticiasAppContext : DbContext { public DbSet<Noticia> Noticias { get; set; } } } 4. Con esto listo, se debe configurar Entity Framework (registrar la dependencia) y agregar la conexión a la base de datos. Esto se realiza a través del archivo Startup.cs. En el método ConfigureServices se agregan las configuraciones, encontrará que ya se está agregando Entity Framework y configurado un contexto, este contexto es el que ya se usa para autenticación de usuarios. Pero debemos agregar el nuevo contexto para las Noticias. // Add EF services to the services container. services.AddEntityFramework() .AddSqlServer() .AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration["Data:DefaultConnection :ConnectionString"])) .AddDbContext<NoticiasAppContext>(options => options.UseSqlServer(Configuration["EntityFramework:Conn ectionString"])); 5. Como ve en la sección de Configuration de este nuevo DbContext hay un string, este es el que indica a cual base de datos conectarse. Esta información se extrae del archivo config.json. Este archivo ya cuenta con un connection string, utilizado para la administración de usuarios fuera de caja. ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 60 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 61 { "AppSettings": { "SiteTitle": "wm.website.ui" }, "Data": { "DefaultConnection": { "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnet5wm.website.ui-a913355d-72f6-4d80-892a19699864e285;Trusted_Connection=True;MultipleActiveRes ultSets=true" } }, "EntityFramework": { "ConnectionString": <conexion a su base de datos> } } 6. Reemplace <conexion a su base de datos> por el connectionstring de su base de datos, ya sea SQL Server o LocalDB. 7. Con esto listo, proceda a compilar el proyecto. 8. Volveremos al ViewComponent de Noticias y reemplazaremos las noticias locales por unas salidas de base de datos. En el archivo ViewComponentes/BannerInteractivoViewCompone nt.cs. La lógica a continuación limpia la base de datos, agrega las noticias a la base de datos y luego las extrae para mostrarlas al usuario, estos datos son de prueba, también conocidos como Seed. using Microsoft.AspNet.Mvc; using System.Collections.Generic; using System.Linq; using wm.website.ui.Models; namespace <sunombredeespacio>.ui.ViewComponents { public class BannerInteractivoViewComponent : ViewComponent { List<Noticia> noticias = new List<Noticia>(); NoticiasAppContext db; public BannerInteractivoViewComponent(NoticiasAppContext _context) { db = _context; } public IViewComponentResult Invoke() { // Limpiemos la base de datos if (db.Noticias.Count() > 0) db.Noticias.RemoveRange(db.Noticias); db.SaveChanges(); // Recreemos los 3 archivos db.Noticias.AddRange(new List<Noticia>() { new Noticia() { Id=1, Titulo="Costa Rica en el puesto #13 de FIFA", Descripcion="Est porta ac magna lundium? Amet eros. Lorem cum ut auctor vel integer mus tortor, adipiscing platea penatibus, in placerat, lectus adipiscing! Ultrices scelerisque adipiscing parturient!" }, new Noticia() { Id=1, Titulo="Nuevo ASP.NET 5", Descripcion="Est porta ac magna lundium? Amet eros. Lorem cum ut auctor vel integer mus tortor, adipiscing platea penatibus, in placerat, lectus adipiscing! Ultrices scelerisque adipiscing parturient!" }, new Noticia() { Id=1, Titulo="¡Hololens está aquí!", Descripcion="Est porta ac magna lundium? Amet eros. Lorem cum ut auctor vel integer mus tortor, adipiscing platea penatibus, in placerat, lectus adipiscing! Ultrices scelerisque adipiscing parturient!" } ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 62 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 63 }); db.SaveChanges(); return View(db.Noticias.ToList()); } } } 9. Ahora, reemplace el contenido del archivo Views/Shared/Components/BannerInteractivo\Defaul t.cshtml, para que en lugar de sacar los datos de una lista de strings, utilice un objeto que vendrá de la base de datos (el css se agrega en el mismo archivo solamente por simplicidad, no es una buena práctica bajo ninguna razón). Énfasis en lo que está en negrita. @model List<Noticia> <h2>¡Esto podría venir de una base de datos!</h2> <div class="bannerNoticias"> <p>Noticias</p> @foreach (var item in Model) { <div class="noticias"> <h4>@item.Titulo</h4> <p>@item.Descripcion</p> </div> } <div class="clearer"></div> </div> <style> .bannerNoticias { border: solid 1px #aaa; border-radius: 10px; padding: 12px; } .bannerNoticias .noticias { display: inline-block; float: left; max-width: 200px; font-size: 12px; } .clearer { clear: both; } </style> 10. Ahora, el siguiente procedimiento es porque ASP.NET 5 sigue en proceso, pero más adelante será más simple. a. Abra el command prompt (busca cmd en las aplicaciones instaladas en Windows). b. Utilice la herramienta cd para ir al folder del proyecto, por ejemplo “Documents\Visual Studio 2015\Projects\wm.website.ui\src\wm.website.ui c. Corra los siguientes comandos para habilitarle el Migration al Code First (para que pueda crear la base de datos por primera vez y demás) i. dnvm install 1.0.0-beta5 ii. dnvm use 1.0.0-beta5 iii. dnx . ef migration add MyFirstMigration –c NoticiasAppContext iv. dnx . ef migration apply –c NoticiasAppContext 11. Al concretar este punto, ejecute la aplicación (F5) se podrán ver las noticias pero saliendo de una base de datos SQL Server. ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 64 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 65 Usando Dependency Injection Como mencioné en capítulos anteriores ASP.NET 5 unifica y ordena el uso de Dependency Injection en MVC, Web API y SignalR. En este ejemplo veremos cómo podemos aprovechar fácilmente este contenedor para inyectar nuestros propios servicios en todas las secciones de nuestra app sin tener que andar agregando y heredando dependencias entre clases. En el ejemplo anterior parte del código que se implementó era: public BannerInteractivoViewComponent(NoticiasAppContext _context) Sin embargo a la hora de invocarlo no se está pasando el parámetro _context a la hora de inicializarlo, esto es porque el contenedor de Dependency Injection se encarga arreglar esa dependencia e “inyectarla” al componente. Vamos a hacer un ejercicio creando nuestro propio servicio e inyectándolo a nuestra aplicación. 1. En el folder Services, cree un archivo llamado ErrorLogger.cs. 2. Agregue el siguiente contenido en la clase: public class ErrorLogger : IErrorLogger { public bool init { get; set; } = false; public ErrorLogger() { // aqui puede inicializar cualquier componente interno init = true; } public void LogError(Exception ex) { // aqui se registrarían errores a la base de datos } } public interface IErrorLogger { void LogError(Exception ex); } 3. Simplemente al inicializar una instancia de la clase se va a colocar la variable init, para así confirmar cuando lo inyectemos que fue inicializado. 4. Como puede ver es una clase sin lógica interna, así nos concentramos en como inyectarlo y no tanto en que hace, lo cual es irrelevante. 5. Vaya a la clase HomeController y agregue el siguiente constructor: IErrorLogger logger { get; set; } public HomeController(IErrorLogger log) { logger = log; } 6. Cómo puede ver, el constructor está recibiendo un parámetro que nadie le está pasando a la hora de invocarlo. Por ende si lo ejecutamos (F5) va a lanzar un error. ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 66 ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 67 7. Aquí es donde Dependency Injection entra en juego y resuelve esa dependencia sin que nosotros se lo indiquemos explícitamente a la hora de inicializarlo. 8. Vaya al archivo Startup.cs 9. Y en el método ConfigureServices agregue la siguiente línea en cualquier parte: services.AddTransient<IErrorLogger, ErrorLogger>(); 10. Al agregarlo a través de la función “AddTransient” el contenedor lo inyectará cuando un método lo pida y quien lo invoque no lo pase por parámetros lo inyectará. CONCLUSIÓN Cómo hemos podido ver, ASP.NET 5 trae muchísimas mejoras y es un framework sumamente robusto para aplicaciones web complejas. Espero sinceramente que este libro les sea de utilidad para adentrarse a tópicos más complejos, que sea una referencia ligera para sus proyectos, sin embargo no espero que lo utilicen como una referencia definitiva al lenguaje, el patrón o el framework. Dependiendo del éxito de este libro, estaré tratando de sacar otros más avanzados y de los cuales tengo algunos temas en mente, tales como características avanzadas en MVC, aplicaciones MVC 6 con AngularJS, Web API avanzado, Microsoft Azure, entre otros. Así que agradezco si pudieran brindarme feedback de este, mi primer libro técnico. Gracias a su feedback estaré enviándoles a su correo electrónico cuando saque actualizaciones de esta serie u otros libros de interés que genere en español. Contacto Email: [email protected] Twitter: @tewar93 http://waltermontes.com ASP.NET MVC 6 - UNA GUÍA INTRODUCTORIA 68