Lab de Azure para desarrolladores - Websites con MVC y EF

Intermedio

Bienvenidos al segundo artículo de la serie de HOL(= Hands On Lab) que he diseñado para que aprendas los fundamentos sitios web en Azure. En esta oportunidad integraremos otras tecnologías de Microsoft para crear un sitio web a la velocidad de la luz.

Como obtener una suscripción en Azure

Puedes obtenerlas de muchas formas

  1. A través del trial, este trial es de 200 USD que te regala microsoft para que pruebes lo que quieras: Try it Now Aunque es gratis se requiere tarjeta de crédito, más como un procedimiento de verificación que cualquier cosa. Te descuentan un dolar de prueba y en 24 horas te lo devuelven
  2. Con una suscripción normal de pago
  3. Por medio del programa BizSpark, si eres emprendedor puedes registrarte en este programa y Microsoft te apoyara en tu emprendimiento con un montón de beneficios, entre los que se encuentran 150 USD al mes durante tres años para consumir servicios en Azure. Puedes ver este video para más info:

4. Si tu, o la empresa para la que trabajas tienen una suscripción a MSDN esta viene tambien con un bono mensual gratuito para consumir servicios en Azure.

5. Sitios web de Azure que duran una hora y es GRATIS Try Azure WebSites

Bienvenidos al segundo artículo de la serie de HOL(= Hands On Lab) que he diseñado para que aprendas los fundamentos sitios web en Azure. En esta oportunidad integraremos otras tecnologías de Microsoft para crear un sitio web a la velocidad de la luz.

Tarea 1 - Crear un sitio web ASP.Net MVC desde Visual Studio

  1. Abrimos Visual Studio,debemos asegurarnos de tener instalada la última versión del Microsoft Azure SDK para Visual Studio
  2. En el menú View escogemos la opción Server Explorer
    Server Explorer
  3. Allí debemos identificar el explorador de servidores donde esta el nodo de Azure
    azure on server explorer
  4. Sobre el nodo de Websites damos click derecho > "Crear nuevo sitio"
    azure websites
  5. Configuramos el sitio con un nombre y una zona adecuada
    azure websites dialog
  6. Una vez se halla creado el sitio, desde Visual Studio creamos un nuevo proyecto como se ve en la gráfica
    visual studio asp.net
  7. Luego lo configuramos así
    asp.net mvc
  8. Esto desplegará el diálogo de creación del website, pero como lo hicimos al comienzo debemos cancelar esta acción, en este dialogo no es posible adjuntar la solución a un sitio ya creado.
  9. Presionamos [F5] para que la solución se lance en el browser
  10. Una vez abierta hacemos click en "Register"
    register on website
  11. Diligenciamos el formulario de registro
  12. Una vez registrados notaremos que para el sitio ya hemos iniciado sesión
    asp.net login
  13. Dónde se guarda esta información? en algún momento indicamos que usaríamos un motor de BD? Cuál es la BD? Cómo accedo a ella?. Son las preguntas que espero te estés haciendo, sino en todo caso ahora las tienes.
  14. Desde Visual Studio detenemos el sitio web
    stop debugging
  15. En el proyecto de Visual Studio abrimos el archivo \Web.config
  16. Estando allí buscamos el siguiente fragmento de código xml (o similar aprox. línea 11)
   <connectionStrings>
    <add name="DefaultConnection" 
         connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-MyMVCSite-20150319030244.mdf;Initial Catalog=aspnet-MyMVCSite-20150319030244;Integrated Security=True"
         providerName="System.Data.SqlClient" />
  </connectionStrings>

17. Este contiene las cadenas de conexión a base de datos, puntualmente tenemos allí una cadena de conexión a una base de datos SQL Local DB. Esta es una BD de archivo.

18. Copiamos de allí el equivalente a este valor (LocalDb)\v11.0

19. En VS vamos el menu View y seleccionamos "SQL Server Object Explorer"
sql server object explorer

20. Desde el panel del "SQL Server Object Explorer" damos click derecho en el nodo principal y seleccionamos "Add SQL Server"
sql server object explorer

21. En el cuadro de dialogo ponemos el nombre del servidor de BD copiado anteriormente y en tipo de autenticación seleccionamos "Windows Authentication"
sql server object explorer

22. En el panel de SQL Server despliega el nodo cuya DB tiene un nombre relacionado con el proyecto y allí despliega el listado de tablas.
sql server object explorer

23. Esta BD y sus tablas no fueron creadas por nosotros en ningún momento, ni tampoco por Visual Studio al crear la solución. Estas fueron creadas por una tecnología llamada Entity Framework especificamente EF Code First. EF es un ORM (Object Relational Mapping) es decir un componente capaz de mapear modelos de datos como si fueran entidades de código. Hay carias formas de trabajarlo.

- Model First : Primero creas un modelo gráfico (realmente es un xml pero VS te lo deja manipular como gráfico) que representa los datos y con base en el se crean las tablas de base de datos y las clases que las representan en el código (entidades)

- Database First: Crear primero el modelo en la base de datos, con base en el automáticamente se infiere el modelo y las entidades

- Code First: Creas primero las clases y tanto modelo como las tablas en la bd se crean automáticamente con base en el.

24. Lo que sucedió con la autenticación es que la librería de autenticación ya tiene definido un modelo con base en el cual se infieren sus clases y de paso la estructura de BD. Al detectar que no hay base de datos el motor procedió a crearla automáticamente con base a los datos de acceso depositados en el archivo web.config. Esto sucedió en tiempo real, apenas presionaste el botón "Registrarse" ya que es en ese momento cuando detectó que no había BD.

Tarea 2 - Diseño de un modelo de datos

Podemos hacer uso de todas las ventajas que posee Entity Framework así que crearemos nuestro propio modelo de datos y de paso haremos uso de la funcionalidad de "Andamiaje" (Scaffolding) que tiene Visual Studio para crear vistas en nuestro sitio web que utilicen dicho modelo de datos.

  1. En el proyecto de VS damos click derecho sobre la carpeta "Models" y seleccionamos Add>Class
    add model MVC
  2. En el dialogo que aparece creamos una clase en el archivo Person.cs, abrimos ese archivo
  3. Al haberlo creado de esa forma la clase esta marcada por defecto como public , dentro de la clase definimos las propiedades que se ven a continuación
     public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }

4. Esta clase será nuestro modelo, EF inferirá la estructura de BD tomándola como base. Es importante notar que la clase es muy sencilla, es lo que se llama una entidad POCO (Plain Old Class Object, a veces Plain Old CLR Object) , es decir una clase sin ningún atributo, herencia o modificador significativo.

5. EF funciona por defecto de acuerdo a una convención de nombres de componentes, esta clase tiene un campo llamado Id y para EF esto indica que este campo es el equivalente a la llave primaria en una BD. Sino tuviésemos un campo Id en esta clase tendríamos que indicarle a EF cual campo es el Id de la Base de datos como se ve en el siguiente ejemplo. (no modifiques tu código, solo observa)

 using System.ComponentModel.DataAnnotations;

namespace MyMVCSite.Models  
{
    public class Person
    {
        [Key]
        public int MiIdPersonalizado { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

Tarea 3 - Creación de controladores y vistas

  1. Como ya tenemos definido nuestro modelo de datos debemos ahora asociarlo con un Contexto de base de datos de tal forma que el proceso se automatice. También, pensando en MVC, debemos crear un controlador y unas vistas para tener la funcionalidad de la aplicación. Aunque podemos crear todo esto a mano VS nos puede echar una mano con el andamiaje automatizando la creación de estos componentes.
  2. Sobre la carpeta "Controllers" damos click derecho Add>Controller
    add controller MVC
  3. Esto despliega una lista de selección, en este debemos seleccionar la opción "MVC Controller with views, using Entity Framework"
    add controller MVC
  4. Al adicionarlo se desplegará el siguiente panel de configuración en el cual debemos establecer:
    • Model Class: Person - Que es el modelo que recién hemos creado, selecciónalo de la lista
    • Data Context: Ya hay uno creado, pero crearemos uno nuevo haciendo click en + y lo nombramos MyModelsContext
    • El resto lo dejamos como esta por defecto, incluyendo el nombre del controlador
      add new controller MVC dialog
  5. Si has hecho las instrucciones al pie de la letra te saldrá este mensaje de error
    add new controller MVC error
  6. Siempre que hayamos creado un nuevo modelo debemos compilar la solución, de esta forma el andamiaje funcionará sin problemas. Compilemos y repitamos los pasos.

El DataContext y el Modelo -- Mvc

  1. Revisemos ahora que es lo que ha sucedido, en VS vamos a la carpeta Models, allí encontraremos un archivo MyModelsContext.cs el cual contiene el contexto de base de la base datos. Examinémoslo.
     public class MyModelsContext : DbContext
    {
        public MyModelsContext() : base("name=MyModelsContext")
        {
        }
        public DbSet<Person> People { get; set; }  
    }

2. Es una clase que hereda de DBContext, esta clase DBContext hace todo 'el trabajo sucio' resolviendo la conexión y operaciones básicas de la BD. Nunca le hemos dicho que la BD es SQL Local DB, pero el lo sabe por dos motivos.

- En el constructor le hemos pasado como parémetro "MyModelsContext" que es el nombre de la cadena de conexión para la base de datos que se usará, eso nos lleva al web.config donde ahora la encontraremos creada

     <connectionStrings>
        ...
        <add name="MyModelsContext" connectionString="Data Source=(localdb)\v11.0; Initial Catalog=MyModelsContext-20150319161820; Integrated Security=True; MultipleActiveResultSets=True; AttachDbFilename=|DataDirectory|MyModelsContext-20150319161820.mdf"
          providerName="System.Data.SqlClient" />
    </connectionStrings>

- En la última parte de esta cadena de conexión encontramos algo como providerName="System.Data.SqlClient" que es el nombre de un objeto que contiene la lógica necesaria para poder hacer operaciones en esa base datos, es decir la única parte dependiente de la BD en todo lo que hemos hecho es esta última, por ende en teoría cambiando la cadena de conexión y el provider nuestro programa debería funcionar sin mayor problema sin importar la BD a la que nos conectemos. En la práctica hay unos escenarios que requieren cambios menores en otras partes del software.
3. Otra cosa importante que vemos en MyModelsContext.cs es DbSet<Person> People que no es más que la forma de acceder a la tabla persona en la base de datos. Si tuviesemos más clases "Modelo" asociadas al mismo DataContext aparecería una lista por cada uno de ellos.

4. Otra cosa que notarás es que el modelo se llama Person pero en el DataContext se hace referencia a People que es el plural de Person. Cosa que nunca hicimos nosotros. El motor de VS + EF es capaz de inferir como pluralizar una palabra, por defecto lo hace en Inglés pero eventualmente se puede configurar para que lo haga en Español.

Las vistas (Views) -- mVc

  1. En el proyecto vamos a la carpeta Views\People allí encontraremos varios archivos con extensión .cshtml que en escencia son archivos html + Razor, un lenguaje derivado de C# optimizado para un entorno de generación de HTML inline.
    mvc views folder
  2. Revisa cada uno de estos archivos, su lógica no es muy elaborada, lo que es más importante por ahora es esta primera línea que esta en todos
    @model MyMVCSite.Models.Person
  3. Esa línea le dice a la vista [es decir el HTML] que los datos que debe mostrar los debe tratar como objetos tipo Person, por ende para que estas listas funcionen, de alguna forma, se les debe enviar datos de tipo Person.
  4. Estas vistas sirven para hacer tal cual lo que su nombre indica, el andamiaje las ha creado para ahorranos trabajo. Veremos más adelante como funcionan.

El Controller -- mvC

  1. En el proyecto vamos a la carpeta Controllers\PeopleController , como puedes ver el controlador tambien ha pluralizado el sustantivo Person. Un controlador normal de ASP.Net MVC hereda de la clase Controller como puedes ver en el fuente. Como usamos el andamiaje podemos observar que el controller creado hace referencia al DataContext MyModelsContext.
  2. El controlador tiene una serie de acciones (métodos), una acción es lo que se activa cada vez que se llama una URL del sitio. En este ejemplo vemos como se activa esta acción al llamar la URL "People/Create", toda acción devuelve una respuesta ActionResult, si la acción esta relacionada con mostrar una página entonces retornará View, otras veces puede hacer una redirección y otras solo retornar un código Http, por ejemplo 404 - Not Found.
     public ActionResult Create()
    {
        return View();
    }

3. La idea del controlador es mediar entre las vistas y el modelo, como ejemplo veamos la acción Details, esta acción recibe como parámetro un Id de la persona para mostrar sus detalles, este aprámetro le llega por la URL enviada desde el browser, dentro de la acción de hace un proceso para encontrar a la persona buscada y como resultado al final llama a la Vista pasándole como parámetro un tipo Person. Lo cual coincide con lo que observamos en el archivo Views\People\Details,cshtml que espera como modelo un tipo Person y es con base en este que arma el html.

     public ActionResult Details(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Person person = db.People.Find(id);
        if (person == null)
        {
            return HttpNotFound();
        }
        return View(person);
    }
 @model MyMVCSite.Models.Person
@{ ViewBag.Title = "Details";}
<h2>Details</h2>  
<div>  
    <h4>Person</h4><hr />
    <dl class="dl-horizontal">
        <dt>@Html.DisplayNameFor(model => model.Name)</dt>
        <dd>@Html.DisplayFor(model => model.Name)</dd>
        <dt>@Html.DisplayNameFor(model => model.Age)</dt>
        <dd>@Html.DisplayFor(model => model.Age)</dd>
    </dl>
</div>  

4. MVC al igual que EF funciona por covención de nombres, entonces cada vez que una URL tiene el nombre del controlador

Tarea 4 - Despliegue en una base de datos local

  1. En Visual Studio abrimos el archivo Views\People\Index.cshtml ejecutamos el sitio desde Visual Studio, para ello presionamos [F5] y obtenemos lo siguiente:
    scaffolded view
  2. La url que se ha abiertoes algo como https://localhost:53062/People es decir esta URL por convención llama al PeopleController, al no tener más nada en la URL el controlador por defecto invoca a la acción Index, que a su vez como resultado devuelve una vista, una vez más por convención la vista tiene el mismo nombre que la acción, así que se invoca a la vista Index.cshtml que es la que vemos finalmente en el browser.
  3. Procedemos a crear un nuevo Person haciendo click en "Create New", que sucede? la URL del vínculo esta apuntando a People/Create por ende se llama al controlador People, acción Create sin parámetros y esta acción al terminar invoca a Views\People\Create.cshtml. Llenamos el formulario y le damos click en Create. Para volver de nuevo a la vista Index.
    scaffolded view
  4. Revisa el controlador y las vistas. Analiza que ha sucedido al presionar el botón Create. Has lo mismo luego presionando los link
    1. Edit
    2. Details
    3. Delete
  5. Ingresa 5 personas más en People/Create
  6. Nuevamente, no hemos creado la BD, pero en algún lugar tiene que estar. En el SQL Server Object Explorer damos click derecho en el servicio de base de datos y luego damos Refresh
    SQL Server Obj Explorer
  7. Ahora verifica y habrá aparecido una nueva BD con el mismo nombre que el DataContext generado por el Andamiaje, al revisarla no sorpresivamente veremos una tabla llamada Person
    View table data
  8. Click derecho sobre la tabla >View Data
    View table data
  9. Y ahora tenemos una lista de los registros ingresados en la tabla
    View table data
  10. EF creo el esquema de datos y la BD en el local server la primera vez que abriste People/ . EF trató de hacer la consulta a la BD preconfigurada y al no encontrarla la creo junto con todos sus objetos.

Tarea 5 - Despliegue en Azure Websites y SQL DB

  1. Estando la ejecución detenida, desde Visual Studio damos click derecho sobre el proyecto>publicar
    Publish project
  2. Esto abrirá el siguiente cuadro de dialogo, aquí damos click en "Microsoft Azure Websites"
    Azure websites
  3. Puede que se requiera que inicies sesión en tu cuenta de Azure. Una vez hecho escoge de la lista el website que creaste al inicio de este lab.
    Azure websites
  4. En el siguiente cuadro das publicidad en "Validate Connection" si todo esta OK de una vez click en "Publish"
  5. El sitio se abrirá, navega a People/Index y...
    Azure websites
  6. Esto sucede por que en la nube no existe un server de SQL Local DB, puedes utilizar otras formas de DB de archivo para solucionarlo, pero mejor utilicemos una base de datos en la nube.
  7. En manage.azure.com ve al módulo de bases de datos. Y das click en nuevo.
    Azure websites
  8. Luego selecciona "Quick Create" y diligencia los campos, recuerda seleccionar Este de EE.UU y recordar el usuario y contraseña que has usado.
    Azure websites
  9. Creamos la base de datos, luego damos click sobre la BD creada y en el panel que se abre, parte inferior damos click en donde muestra la imagen
    Azure websites
  10. Aquí encontramos diferentes cadenas de conexión par utilizar según sea el lenguaje de programación que estamos usando, para este caso copiamos la que dice ADO.Net.
    Azure websites
  11. Regresamos a Visual Studio, abrimos el archivo web.config y allí cambiamos la cadena de conexión MyModelsContext para asignarle el valor que acabamos de copiar. Recuerda reemplazar el password y no usar los corchetes.
     <connectionStrings>
        ...
<add name="MyModelsContext"  
      connectionString="Server=tcp:v9yocxnhrs.database.windows.net,1433;Database=MySQLDB;User ID={aquí_va_tu_usuario}@v9yocxnhrs;Password={aquí_va_tu_contraseña};Trusted_Connection=False;Encrypt=True;Connection Timeout=30;"
      providerName="System.Data.SqlClient" />

12. Regresa al módulo de bases de datos en Azure, en la última columna de la BD creada se encuentra un vínculo para ir al servidor que la contiene, dale click.
Azure websites

13. En el servidor ve a la pestaña configurar. Dale click en el botón que indica la imagen, esto permitirá que incluso corriendo la BD localmente te puedas conectar a tu BD Remota, ya que has agregado tu IP pública al firewall. Más abajo asegurate de tener el switch en SI, esto autoriza a que otros sitios de tu suscripción de Azure puedan conectarse a la BD sin problema.
Azure websites

12. Guarda los cambios, vuelve a publicar la solución y revisa el sitio de Azure nuevamente visitando /People

13. Todo debe funcionar perfecto, revisa la funcionalidad, crea nuevos registros, consulta , edita etc.

FIN