Introducción a Azure Cloud Services (clásico) y ASP.NET
Información general
Importante
Cloud Services (clásico) ahora está en desuso para todos los clientes a partir del 1 de septiembre de 2024. Microsoft detendrá y apagará las implementaciones en ejecución existentes y los datos se perderán de forma permanente a partir de octubre de 2024. Las nuevas implementaciones deben utilizar el nuevo modelo de implementación basado en Azure Resource Manager Azure Cloud Services (soporte extendido) .
Este tutorial muestra cómo crear una aplicación .NET multinivel con un front-end ASP.NET Model-View-Controller (MVC) e implementarla en un servicio en la nube de Azure. La aplicación usa Azure SQL Database, el servicio Azure Blob service y el servicio Azure Queue service. Puede descargar el proyecto de Visual Studio desde la Galería de código de Microsoft Developer Network (MSDN).
En el tutorial se muestra cómo crear y ejecutar la aplicación localmente, cómo implementarla en Azure y ejecutarla en la nube y, por último, cómo crearla desde cero. Puede comenzar por crearla desde cero y después llevar a cabo los pasos de prueba e implementación si lo prefiere.
Aplicación Contoso Ads
La aplicación es un tablón de anuncios publicitario. Los usuarios crean un anuncio introduciendo texto y cargando una imagen. Pueden ver una lista de anuncios con imágenes en miniatura y ver la imagen a tamaño completo cuando seleccionan un anuncio para ver los detalles.
La aplicación usa el patrón de trabajo centrado en colas para descargar el trabajo de uso intensivo de CPU de creación de miniaturas y pasarlo a un proceso back-end.
Arquitectura alternativa: App Service y WebJobs
En este tutorial se muestra cómo ejecutar un front-end y un back-end en un servicio en la nube de Azure. Una alternativa es ejecutar el front-end en Azure App Service y usar la característica WebJobs para el back-end. Para ver un tutorial en el que se utiliza WebJobs, consulte Introducción al SDK de Azure WebJobs. Para información sobre cómo elegir los servicios que mejor se adapten a su escenario, consulte Comparación de Azure App Service, Cloud Services y Virtual Machines.
Objetivos de aprendizaje
- Habilitar su equipo para desarrollar contenido de Azure mediante la instalación del SDK de Azure.
- Creación de un proyecto de servicio en la nube de Visual Studio con un rol web de ASP.NET MVC y un rol de trabajo
- Prueba del proyecto de servicio en la nube localmente mediante el Emulador de Azure Storage.
- Publicación del proyecto en la nube en un servicio en la nube de Azure y prueba usando una cuenta de almacenamiento de Azure.
- Carga de archivos y almacenamiento de los mismos en Azure Blob service.
- Uso del servicio Cola de Azure para comunicación entre niveles.
Requisitos previos
En este tutorial se da por supuesto que comprende los conceptos básicos sobre Azure Cloud Services como, por ejemplo, la terminología rol web y rol de trabajo. También se supone que sabe trabajar con proyectos ASP.NET MVC o Web Forms en Visual Studio. La aplicación de ejemplo usa MVC, pero la mayoría del tutorial también se aplica a Web Forms.
Puede ejecutar la aplicación localmente sin una suscripción de Azure, pero necesitará una para implementar la aplicación en la nube. Si aún no la tiene, puede activar los beneficios de suscripción a MSDN o registrarse para obtener una evaluación gratuita.
Las instrucciones del tutorial funcionan con cualquiera de los productos siguientes:
- Visual Studio 2013
- Visual Studio 2015
- Visual Studio 2017
- Visual Studio 2019
Si no tiene uno de ellos, Visual Studio se puede instalar automáticamente al instalar el SDK de Azure.
Arquitectura de la aplicación
La aplicación almacena anuncios en una base de datos SQL, usando Entity Framework Code First para crear las tablas y acceder a los datos. Por cada anuncio, la base de datos almacena dos direcciones URL, una para la imagen a tamaño completo y otra para la miniatura.
Cuando un usuario carga una imagen, el front-end que se ejecuta en un rol web almacena dicha imagen en un blob de Azurey la información del anuncio en la base de datos con una dirección URL que apunta al blob. Al mismo tiempo, escribe mensaje en una cola de Azure. Un proceso back-end que se ejecuta en un rol de trabajo sondea la cola periódicamente para ver si hay nuevos mensajes. Cuando aparece un nuevo mensaje, el rol de trabajo crea una miniatura para la imagen y actualiza el campo de base de datos de la dirección URL de la miniatura para ese anuncio. El siguiente diagrama muestra cómo interactúan las partes de la aplicación:
Configuración del entorno de desarrollo
Para comenzar, configure su entorno de desarrollo con Visual Studio y Azure SDK.
Visual Studio 2019 incluye Azure SDK. Si usa Visual Studio 2019, no se necesita ninguna configuración adicional para el entorno de desarrollo.
Para Visual Studio 2015, haga clic en el vínculo siguiente para instalar Azure SDK para Visual Studio 2015.
Para Visual Studio 2013, haga clic en el vínculo siguiente para instalar Azure SDK para Visual Studio 2013.
Si no tiene instalado Visual Studio, use lo siguiente para instalar Visual Studio 2019 con Azure SDK.
Nota:
Según el número de dependencias de SDK que tenga ya en la máquina, la instalación del SDK puede tardar tiempo, desde unos minutos a media hora o más.
Descarga y ejecución de la solución completa
Descargue y descomprima la solución completa.
Inicie Visual Studio.
En el menú Archivo, seleccione Abrir proyecto, vaya a la ubicación donde descargó la solución y abra el archivo de la solución.
Para compilar la solución, presione Ctrl+MAYÚS+B.
De forma predeterminada, Visual Studio restaura automáticamente el contenido del paquete NuGet, que no se incluyó en el archivo .zip. Si los paquetes no se restauran, para instalarlos manualmente, vaya al cuadro de diálogo Administrar paquetes NuGet para la solución y haga clic en el botón Restaurar en la parte superior derecha.
En el Explorador de soluciones, asegúrese de que ContosoAdsCloudService se encuentra seleccionado como proyecto de inicio.
Si va a usar Visual Studio 2015 o una versión superior, cambie la cadena de conexión del servidor SQL Server en el archivo Web.config del proyecto ContosoAdsWeb y en el archivo ServiceConfiguration.Local.cscfg del proyecto ContosoAdsCloudService. En cada caso, cambie "(localdb) \v11.0" por "(localdb) \MSSQLLocalDB".
Para ejecutar la aplicación, presione CTRL+F5.
Cuando ejecuta un proyecto de servicio en la nube localmente, Visual Studio invoca automáticamente al emulador de proceso y al emulador de almacenamiento, ambos de Azure. El emulador de proceso usa los recursos del equipo para simular los entornos de los roles web y de trabajo. El emulador de almacenamiento usa una base de datos LocalDB de SQL Server Express para simular el almacenamiento en la nube de Azure.
La primera vez que ejecuta un proyecto de servicio en la nube, los emuladores tardan alrededor de un minuto en iniciarse. Cuando el inicio del emulador finaliza, se abre el explorador predeterminado en la página de inicio de la aplicación.
Seleccione Crear un anuncio.
Escriba algunos datos de prueba y seleccione una imagen .jpg para cargar; a continuación, seleccione Crear.
La aplicación irá a la página Index, pero no mostrará una miniatura para el nuevo anuncio porque ese procesamiento todavía no se ha llevado a cabo.
Espere un momento y actualice la página Index para ver la miniatura.
Seleccione Detalles correspondiente a su anuncio para ver la imagen a tamaño completo.
Ha estado ejecutando la aplicación completamente en su equipo local, sin conexión a la nube. El emulador de almacenamiento almacena los datos de cola y de blob en una base de datos LocalDB de SQL Server Express y la aplicación hace lo propio con los datos del anuncio almacenándolos en otra base de datos LocalDB. Entity Framework Code First creó automáticamente la base de datos de anuncios la primera vez que la aplicación web intentó acceder a ella.
En la siguiente sección configura la solución para usar recursos en la nube de Azure para colas, blobs y la base de datos de aplicación cuando se ejecuta en la nube. Podría hacer esto si quisiera seguir trabajando localmente, pero usar recursos de almacenamiento de nube y base de datos. Es simplemente una cuestión de configurar las cadenas de conexión, que ahora verá cómo hacerlo.
Implementar la aplicación en Azure
Lleve a cabo los pasos siguientes para ejecutar la aplicación en la nube:
- Cree un servicio en la nube de Azure.
- Cree una base de datos en Azure SQL Database.
- Cree una cuenta de almacenamiento de Azure.
- Configurar la solución para usar la base de datos cuando se ejecute en Azure
- Configure la solución para usar la cuenta de almacenamiento de Azure cuando se ejecuta en Azure.
- Implementar el proyecto en su servicio en la nube de Azure.
Crear un servicio en la nube de Azure
Un servicio en la nube de Azure es el entorno en el que se ejecuta la aplicación.
En el explorador, abra Azure Portal.
Seleccione Crear un recurso > Compute > Servicio en la nube.
En el cuadro de entrada nombre del sistema de nombres de dominio (DNS), escriba un prefijo de dirección URL para el servicio en la nube.
Esta dirección URL tiene que ser única. Se muestra un mensaje de error si el prefijo que elige ya está en uso.
Especifique un nuevo grupo de recursos para el servicio. Seleccione en Crear nuevo y luego escriba un nombre en el cuadro de entrada del grupo de recursos, por ejemplo, CS_contososadsRG.
Elija la región en la que desea implementar la aplicación.
Este campo especifica el centro de datos en el que se hospeda el servicio en la nube. Para una aplicación de producción, elegiría la región más cercana a sus clientes. Para este tutorial, elija la región más cercana a usted.
Seleccione Crear.
En la siguiente imagen, se crea un servicio en la nube con la dirección URL CSvccontosoads.cloudapp.net.
Creación de una base de datos de Azure SQL Database
Cuando la aplicación se ejecute en la nube, usa una base de datos basada en la nube.
En el de Azure Portal, seleccione Crear un recurso > Bases de datos > SQL Database.
En el cuadro Nombre de base de datos , escriba contosoads.
En el Grupo de recursos, elija Usar existente y seleccione el grupo de recursos usado para el servicio en la nube.
En la imagen siguiente, seleccioneServidor - Definir la configuración necesaria y Crear un servidor nuevo.
Asimismo, si su suscripción ya tiene un servidor, puede seleccionarlo en la lista desplegable.
En el cuadro Nombre del servidor, escriba csvccontosodbserver.
Complete los campos Nombre de inicio de sesión y Contraseña con los datos de un administrador.
Si seleccionó Crear un servidor nuevo, no escribirá aquí un nombre y una contraseña existentes. Escribirá un nombre y una contraseña nuevos que definirá ahora para usarlos más adelante cuando acceda a la base de datos. Si seleccionó un servidor creado anteriormente, se le pedirá la contraseña de la cuenta de usuario administrativa que ya creó.
Elija la misma ubicación que eligió para el servicio en la nube.
Cuando el servicio en la nube y la base de datos se encuentran en diferentes centros de datos (regiones diferentes), aumenta la latencia y se incurre en cargos por el ancho de banda fuera del centro de datos. El ancho de banda del centro de datos es gratuito.
Marque la opción Permitir que los servicios de Azure accedan al servidor.
Seleccione Seleccionar para el nuevo servidor.
Seleccione Crear.
Creación de una cuenta de Azure Storage
Una cuenta de almacenamiento de Azure proporciona recursos para almacenar datos de cola y blob en la nube.
En una aplicación real, normalmente crearía cuentas independientes para los datos de aplicación frente a los datos de registro, y cuentas diferentes para datos de prueba frente a datos de producción. En este tutorial, usará solo una cuenta.
En el Azure Portal, seleccione Crear un recurso >Almacenamiento > cuenta de almacenamiento: blob, archivo, tabla, cola.
En el cuadro Nombre, escriba un prefijo de dirección URL.
Este prefijo más el texto que ve en el cuadro es la dirección URL única de la cuenta de almacenamiento. Si el prefijo que escriba ya está en uso por otra persona, elija otro prefijo.
Establezca Modelo de implementación en Clásica.
Establezca la lista desplegable Replicación en Almacenamiento con redundancia local.
Cuando se habilita la replicación geográfica para una cuenta de almacenamiento, el contenido almacenado se replica en un centro de datos secundario para permitir la conmutación por error en caso de que se produzca un desastre importante en la ubicación principal. La replicación geográfica puede suponer costes adicionales. Lo normal es que no quiera pagar por el servicio de replicación geográfica para las cuentas de prueba y desarrollo. Para obtener más información, consulte Creación, administración o eliminación de una cuenta de almacenamiento.
En el Grupo de recursos, seleccione Usar existente y seleccione el grupo de recursos usado para el servicio en la nube.
Establezca la lista desplegable Ubicación en la misma región que eligió para el servicio en la nube.
Cuando la cuenta de almacenamiento y la cuenta de almacenamiento se encuentren en centros de datos diferentes (distintas regiones), la latencia aumentará y se le cobrará el ancho de banda no perteneciente al centro de datos. El ancho de banda del centro de datos es gratuito.
Los grupos de afinidad de Azure proporcionan un mecanismo para minimizar la distancia entre los recursos de un centro de datos, lo que puede reducir la latencia. En este tutorial no se usan grupos de afinidad. Para obtener información, consulte Creación de un grupo de afinidad en Azure.
Seleccione Crear.
En la imagen, se crea una cuenta de almacenamiento con la dirección URL
csvccontosoads.core.windows.net
.
Configurar la solución para usar la base de datos de Azure SQL Database cuando se ejecute en Azure
El proyecto web y el proyecto de rol de trabajo tienen cada uno su propia cadena de conexión de base de datos, y cada uno necesita apuntar a la base de datos de Azure SQL Database cuando la aplicación se ejecuta en Azure.
Use una transformación Web.config para el rol web y una configuración de entorno de servicio en la nube para el rol de trabajo.
Nota:
En esta sección y en la siguiente almacenará credenciales en archivos de proyecto. No almacene información confidencial en repositorios de código fuente público.
En el proyecto ContosoAdsWeb, abra el archivo de transformación Web.Release.config del archivo Web.config de la aplicación, elimine el bloque de comentario que contiene un elemento
<connectionStrings>
y pegue el siguiente código en su lugar.<connectionStrings> <add name="ContosoAdsContext" connectionString="{connectionstring}" providerName="System.Data.SqlClient" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/> </connectionStrings>
Deje el archivo abierto para editarlo.
En Azure Portal, elija Base de datos SQL en el panel izquierdo, seleccione la base de datos que creó para este tutorial y, a continuación, seleccione Mostrar cadenas de conexión.
El portal muestra las cadenas de conexión con un marcador de posición para la contraseña.
En el archivo de transformación Web.Release.config, elimine
{connectionstring}
y pegue en su lugar la cadena de conexión ADO.NET de Azure Portal.En la cadena de conexión que pegó en el archivo de transformación Web.Release.config, reemplace
{your_password_here}
por la contraseña creada para la nueva base de datos SQL.Guarde el archivo.
Seleccione una copia de la cadena de conexión (sin las comillas circundantes) para usar en los pasos siguientes para configurar el proyecto de rol de trabajo.
En el Explorador de soluciones, bajo Roles en el proyecto de servicio en la nube, haga clic con el botón derecho en ContosoAdsWorker y, por último seleccione Propiedades.
Elija la pestaña Configuración .
Cambie Configuración del servicio a Nube.
Seleccione el campo Valor de la configuración de
ContosoAdsDbConnectionString
y pegue la cadena de conexión que copió de la sección anterior del tutorial.Guarde los cambios.
Configurar la solución para usar la cuenta de almacenamiento de Azure cuando se ejecuta en Azure
Las cadenas de conexión de la cuenta de almacenamiento de Azure tanto para el proyecto de rol web como para el proyecto de rol de trabajo, se almacenan en la configuración del entorno en el proyecto de servicio en la nube. Para cada proyecto existe un conjunto independiente de configuraciones para usar cuando la aplicación se ejecuta localmente y cuando se ejecuta en la nube. Actualice la configuración del entorno en la nube tanto para proyectos de rol web como para proyectos de rol de trabajo.
En el Explorador de soluciones, haga clic con el botón derecho en ContosoAdsWeb debajo de Roles en el proyecto ContosoAdsCloudService y después seleccione Propiedades.
Elija la pestaña Configuración . En el cuadro desplegable Configuración del servicio, seleccione Nube.
Seleccione la entrada StorageConnectionString y verá un botón con unos puntos suspensivos (...) al final de la línea. Elija el botón de puntos suspensivos para abrir el cuadro de diálogo Crear cadena de conexión de almacenamiento.
En el cuadro de diálogo Crear cadena de conexión de almacenamiento, seleccione Su suscripción, elija la cuenta de almacenamiento que creó anteriormente y, a continuación, seleccione Aceptar. El explorador le pide las credenciales de la cuenta de Azure si todavía necesita iniciar sesión.
Guarde los cambios.
Siga el mismo procedimiento que usó para la cadena de conexión
StorageConnectionString
para establecer la cadena de conexiónMicrosoft.WindowsAzure.Plugins.Diagnostics.ConnectionString
.Esta cadena de conexión se usa para registro.
Siga el mismo procedimiento que usó para el rol ContosoAdsWeb para establecer ambas cadenas de conexión para el rol ContosoAdsWorker. No olvide establecer Configuración del servicio en Nube.
La configuración del entorno del rol que configuró usando la interfaz de usuario de Visual Studio se almacena en los siguientes archivos en el proyecto ContosoAdsCloudService:
- ServiceDefinition.csdef : define los nombres de los valores.
- ServiceConfiguration.Cloud.cscfg : proporciona valores para cuando la aplicación se ejecuta en la nube.
- ServiceConfiguration.Local.cscfg : proporciona valores para cuando la aplicación se ejecuta localmente.
Por ejemplo, el archivo ServiceDefinition.csdef incluye las siguientes definiciones:
<ConfigurationSettings>
<Setting name="StorageConnectionString" />
<Setting name="ContosoAdsDbConnectionString" />
</ConfigurationSettings>
Y el archivo ServiceConfiguration.Cloud.cscfg incluye los valores introducidos para esas configuraciones en Visual Studio.
<Role name="ContosoAdsWorker">
<Instances count="1" />
<ConfigurationSettings>
<Setting name="StorageConnectionString" value="{yourconnectionstring}" />
<Setting name="ContosoAdsDbConnectionString" value="{yourconnectionstring}" />
<!-- other settings not shown -->
</ConfigurationSettings>
<!-- other settings not shown -->
</Role>
La <Instances>
opción especifica el número de máquinas virtuales en las que Azure ejecuta el código del rol de trabajo. La sección Pasos siguientes incluye vínculos a más información sobre el escalado horizontal a un servicio en la nube
Implementar el proyecto en Azure
En el Explorador de soluciones, haga clic con el botón derecho en el proyecto en la nube ContosoAdsCloudService y después seleccione Publicar.
En el paso Iniciar sesión del asistente Publicar aplicación de Azure, seleccione Siguiente.
En el paso Configuración del asistente, seleccione Siguiente.
La configuración predeterminada de la pestaña Avanzada es correcta para este tutorial. Para obtener más información sobre la pestaña de opciones avanzadas, consulte Asistente para publicar aplicación de Azure.
En el paso Resumen, seleccione Publicar.
Se abrirá la ventana Registro de actividad de Azure en Visual Studio.
Elija en el icono de la flecha derecha para expandir la información de implementación.
La implementación puede tardar 5 minutos o más en completarse.
Cuando se haya completado la implementación, seleccioneURL de aplicación web para iniciar la aplicación.
Ahora puede probar la aplicación creando, viendo y editando algunos anuncios, tal y como hizo cuando ejecutó la aplicación localmente.
Nota:
Cuando termine la prueba, elimine o detenga el servicio en la nube. Aunque no utilice el servicio en la nube, se acumularán cargos porque se reservan recursos de máquina virtual para él. Y si lo deja ejecutando, cualquiera que encuentre su dirección URL puede crear y ver anuncios. En Azure Portal, vaya a la pestaña Información general del servicio en la nube y luego haga clic en el botón Eliminar en la parte superior de la página. Si lo que desea es evitar temporalmente que otros accedan al sitio, haga clic en Detener . En ese caso, los cargos seguirán acumulándose. Puede seguir un procedimiento similar para eliminar la base de datos SQL y la cuenta de almacenamiento cuando ya no las necesite.
Creación de la aplicación desde cero
Si todavía necesita descargar la aplicación completada, hágalo ahora. Copie los archivos desde el proyecto descargado en el nuevo proyecto.
Para crear la aplicación Contoso Ads es necesario llevar a cabo los pasos siguientes:
- Crear una solución de Visual Studio para un servicio en la nube.
- Actualizar y agregar paquetes de NuGet.
- Establecer preferencias del proyecto.
- Configurar cadenas de conexión.
- Agregar archivos de código.
Una vez creada la solución, se asegurará de que el código es único en proyectos de servicios en la nube y blobs y colas de Azure.
Crear una solución de Visual Studio para un servicio en la nube
En Visual Studio, elija Nuevo proyecto from the Archivo .
En el panel de la izquierda del cuadro de diálogo Nuevo proyecto, expanda Visual C# , elija las plantillas Nube y, por último, elija la plantilla Servicio de nube de Azure.
Asigne un nombre al proyecto y a la solución ContosoAdsCloudService y seleccione Aceptar.
En el cuadro de diálogo Nuevo servicio en la nube de Azure , agregue un rol web o de trabajo. Asigne un nombre al rol web ContosoAdsWeb y al rol de trabajo ContosoAdsWorker. (Use el icono del lápiz situado en el panel derecho para cambiar los nombres predeterminados de los roles.)
Cuando use el cuadro de diálogo Nuevo proyecto ASP.NET para el rol web, elija la plantilla MVC y seleccioneCambiar autenticación.
En el cuadro de diálogo Cambiar autenticación, elija Sin autenticación y seleccioneAceptar.
En el cuadro de diálogo Nuevo proyecto ASP.NET, seleccione en Aceptar.
En el Explorador de soluciones, haga clic con el botón derecho en la solución (no en uno de los proyectos) y elija Agregar - Nuevo proyecto.
En el cuadro de diálogo Agregar nuevo proyecto, elija Windows en Visual C# en el panel de la izquierda y, después, seleccione en la plantilla Biblioteca de clases.
Asigne un nombre al proyecto ContosoAdsCommon, y seleccioneAceptar.
Necesita hace referencia al contexto de Entity Framework y al modelo de datos de los proyectos de rol web y de trabajo. Como alternativa, podría definir las clases relacionadas con EF en el proyecto de rol web y hacer referencia a ese proyecto desde el proyecto de rol de trabajo. Pero en este enfoque alternativo, el proyecto de rol de trabajo tendría que hacer referencia a ensamblados web que no necesita.
Actualizar y agregar paquetes de NuGet
Abra el cuadro de diálogo Administrar paquetes de NuGet correspondiente a la solución.
En la parte superior de la ventana, seleccione Actualizaciones.
Busque el paquete WindowsAzure.Storage y, si está en la lista, selecciónelo, elija los proyectos web y de trabajo en los que actualizarlo y, después, seleccioneActualizar.
La biblioteca de cliente de almacenamiento se actualiza con más frecuencia que las plantillas de proyecto de Visual Studio, por lo que es necesario actualizar la versión de un proyecto recién creado.
En la parte superior de la ventana, seleccione Examinar.
Busque el paquete NuGet de EntityFramework e instálelo en los otros tres proyectos.
Busque el paquete NuGet Microsoft.WindowsAzure.ConfigurationManager e instálelo en el proyecto de rol de trabajo.
Establecimiento de preferencias del proyecto
En el proyecto ContosoAdsWeb, establezca una referencia al proyecto ContosoAdsCommon. Haga clic con el botón derecho en el proyecto ContosoAdsWeb y después seleccione Referencias - Agregar referencias. En el cuadro de diálogo Administrador de referencias, seleccione Solución – Proyectos en el panel izquierdo, seleccione ContosoAdsCommon y seleccione Aceptar.
En el proyecto ContosoAdsWorker, establezca una referencia al proyecto ContosoAdsCommon.
ContosoAdsCommon contiene el modelo de datos de Entity Framework y la clase de contexto, que usa el front-end y el back-end.
En el proyecto ContosoAdsWorker, establezca una referencia en
System.Drawing
.Este ensamblado lo usa el back-end para convertir imágenes en miniaturas.
Configurar cadenas de conexión
En esta sección configurará Azure Storage y cadenas de conexión de SQL para pruebas locales. Las instrucciones de implementación que aparecen anteriormente en el tutorial explican cómo configurar las cadenas de conexión para cuando la aplicación se ejecuta en la nube.
En el proyecto ContosoAdsWeb, abra el archivo Web.config de la aplicación e inserte el siguiente elemento
connectionStrings
después del elementoconfigSections
.<connectionStrings> <add name="ContosoAdsContext" connectionString="Data Source=(localdb)\v11.0; Initial Catalog=ContosoAds; Integrated Security=True; MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" /> </connectionStrings>
Si va a usar Visual Studio 2015 o una versión superior, sustituya "v11.0" por "MSSQLLocalDB".
Guarde los cambios.
En el proyecto ContosoAdsCloudService, haga clic con el botón derecho en ContosoAdsWeb bajo Roles y después seleccione Propiedades.
En la ventana de propiedades del rol ContosoAdsWeb, seleccione la pestaña Configuración y, después, en Agregar configuración.
Deje Configuración del servicio establecido en Todas las configuraciones.
Agregue un nuevo valor llamado StorageConnectionString. Establezca Tipo en ConnectionString y Valor en UseDevelopmentStorage=true.
Guarde los cambios.
Siga el mismo procedimiento para agregar una cadena de conexión en las propiedades del rol ContosoAdsWorker.
Mientras sigue en la ventana de propiedades ContosoAdsWorker [Rol], agregue otra cadena de conexión:
Nombre: ContosoAdsDbConnectionString
Escriba: String
Valor: pegue la misma cadena de conexión que usó para el proyecto de rol web. (El ejemplo siguiente es para Visual Studio 2013; no olvide cambiar el origen de datos si copia este ejemplo y va a usar Visual Studio 2015 o una versión superior).
Data Source=(localdb)\v11.0; Initial Catalog=ContosoAds; Integrated Security=True; MultipleActiveResultSets=True;
Agregar archivos de código
En esta sección copiará archivos de código de la solución descargada a la nueva solución. En las secciones siguientes se muestran y explican las partes clave de este código.
Para agregar archivos a un proyecto o una carpeta, haga clic con el botón derecho en el proyecto o carpeta y seleccione Agregar - Elemento existente. Seleccione los archivos que desee y, a continuación, seleccione Agregar. Si se le pregunta si desea reemplazar los archivos existentes, seleccione Sí.
En el proyecto ContosoAdsCommon, elimine el archivo Class1.cs y agregue en su lugar los archivos Ad.cs y ContosoAdscontext.cs desde el proyecto descargado.
En el proyecto ContosoAdsWeb, agregue los siguientes archivos desde el proyecto descargado.
- Global.asax.cs.
- En la carpeta Views\Shared: _Layout.cshtml.
- En la carpeta Views\Home: Index.cshtml.
- En la carpeta Controllers: AdController.cs.
- En la carpeta Views\Ad (cree primero la carpeta): cinco archivos .cshtml.
En el proyecto ContosoAdsWorker, agregue WorkerRole.cs desde el proyecto descargado.
Ahora puede compilar y ejecutar la aplicación tal y como se indicó anteriormente en el tutorial y dicha aplicación usa los recursos de base de datos local y del emulador de almacenamiento.
En la siguiente sección se explica el código relacionado para trabajar con el entorno, blobs y colas de Azure. En este tutorial no se explica cómo crear controladores y vistas MVC usando scaffolding, cómo escribir código Entity Framework que funcione con bases de datos de SQL Server o los fundamentos de la programación asincrónica en ASP.NET 4.5. Para obtener más información sobre estos temas, consulte los siguientes recursos:
- Introducción a MVC 5
- Introducción a EF 6 y MVC 5
- Introducción a la programación asincrónica en .NET 4.5
ContosoAdsCommon - Ad.cs
El archivo Ad.cs define una enumeración para categorías de anuncios y una clase de entidad POCO para información de anuncios.
public enum Category
{
Cars,
[Display(Name="Real Estate")]
RealEstate,
[Display(Name = "Free Stuff")]
FreeStuff
}
public class Ad
{
public int AdId { get; set; }
[StringLength(100)]
public string Title { get; set; }
public int Price { get; set; }
[StringLength(1000)]
[DataType(DataType.MultilineText)]
public string Description { get; set; }
[StringLength(1000)]
[DisplayName("Full-size Image")]
public string ImageURL { get; set; }
[StringLength(1000)]
[DisplayName("Thumbnail")]
public string ThumbnailURL { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime PostedDate { get; set; }
public Category? Category { get; set; }
[StringLength(12)]
public string Phone { get; set; }
}
ContosoAdsCommon - ContosoAdsContext.cs
La clase ContosoAdsContext especifica que la clase Ad se usa en una colección DbSet, cuyo Entity Framework se almacena en una base de datos SQL.
public class ContosoAdsContext : DbContext
{
public ContosoAdsContext() : base("name=ContosoAdsContext")
{
}
public ContosoAdsContext(string connString)
: base(connString)
{
}
public System.Data.Entity.DbSet<Ad> Ads { get; set; }
}
La clase tiene dos constructores. El primero de ellos lo usa el proyecto web y especifica el nombre de una cadena de conexión que se almacena en el archivo Web.config. El segundo constructor le permite pasar la cadena de conexión real usada por el proyecto de rol de trabajo, ya que no tiene un archivo Web.config. Ha visto anteriormente dónde se almacenó esta cadena de conexión. Más adelante, verá cómo el código recupera la cadena de conexión cuando crea una instancia de la clase DbContext.
ContosoAdsWeb - Global.asax.cs
El código llamado desde el método Application_Start
crea un contenedor de blob images y una cola images si todavía no existen. Este código garantiza que cada vez que use una nueva cuenta de almacenamiento o use el emulador de almacenamiento en un equipo nuevo, el código crea automáticamente el contenedor de blobs y la cola necesarios.
El código obtiene acceso a la cuenta de almacenamiento usando la cadena de conexión de almacenamiento del archivo .cscfg .
var storageAccount = CloudStorageAccount.Parse
(RoleEnvironment.GetConfigurationSettingValue("StorageConnectionString"));
Después obtiene una referencia al contenedor de blobs images , crea el contenedor si todavía no existe y establece permisos de acceso en el nuevo contenedor. De forma predeterminada, los nuevos contenedores solamente permiten a los clientes con credenciales de cuenta de almacenamiento acceder a blobs. El sitio web necesita que los blobs sean públicos para que pueda mostrar imágenes usando direcciones URL que apunten a los blobs de imagen.
var blobClient = storageAccount.CreateCloudBlobClient();
var imagesBlobContainer = blobClient.GetContainerReference("images");
if (imagesBlobContainer.CreateIfNotExists())
{
imagesBlobContainer.SetPermissions(
new BlobContainerPermissions
{
PublicAccess =BlobContainerPublicAccessType.Blob
});
}
El código similar obtiene una referencia a la cola images y crea una nueva cola. En este caso no es necesario cambios de permiso.
CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
var imagesQueue = queueClient.GetQueueReference("images");
imagesQueue.CreateIfNotExists();
ContosoAdsWeb - _Layout.cshtml
El archivo _Layout.cshtml establece el nombre de aplicación en el encabezado y pie de página, y crea una entrada de menú "Ads".
ContosoAdsWeb - Views\Home\Index.cshtml
El archivo Views\Home\Index.cshtml muestra vínculos de categoría en la página principal. Los vínculos pasan el valor entero de la enumeración Category
en una variable de cadena de consulta a la página de índice de anuncios.
<li>@Html.ActionLink("Cars", "Index", "Ad", new { category = (int)Category.Cars }, null)</li>
<li>@Html.ActionLink("Real estate", "Index", "Ad", new { category = (int)Category.RealEstate }, null)</li>
<li>@Html.ActionLink("Free stuff", "Index", "Ad", new { category = (int)Category.FreeStuff }, null)</li>
<li>@Html.ActionLink("All", "Index", "Ad", null, null)</li>
ContosoAdsWeb - AdController.cs
En el archivo AdController.cs, el constructor llama al método InitializeStorage
para crear objetos de biblioteca de cliente de Azure Storage que proporcionan una API para trabajar con blobs y colas.
Después, el código obtiene una referencia al contenedor de blobs images tal y como vio antes en Global.asax.cs. Mientras hace eso, establece una directiva de reintentos apropiada para una aplicación web. La directiva de reintentos de retroceso exponencial predeterminada podría provocar que la aplicación web dejara de responder durante más de un minuto en reintentos repetidos por un error transitorio. La directiva de reintentos especificada aquí espera tres segundos después de cada reintento hasta tres reintentos.
var blobClient = storageAccount.CreateCloudBlobClient();
blobClient.DefaultRequestOptions.RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(3), 3);
imagesBlobContainer = blobClient.GetContainerReference("images");
El código similar obtiene una referencia a la cola images .
CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
queueClient.DefaultRequestOptions.RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(3), 3);
imagesQueue = queueClient.GetQueueReference("images");
La mayoría del código del controlador es típico para trabajar con un modelo de datos de usando Entity Framework usando una clase DbContext. Una excepción es el método HttpPost Create
, que carga un archivo y lo guarda en el almacenamiento de blobs. El enlazador de modelos proporciona un objeto HttpPostedFileBase al método.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(
[Bind(Include = "Title,Price,Description,Category,Phone")] Ad ad,
HttpPostedFileBase imageFile)
Si el usuario seleccionó un archivo para cargar, el código carga el archivo, lo guarda en un blob y actualiza el registro de base de datos Ad con una dirección URL que adjunta al blob.
if (imageFile != null && imageFile.ContentLength != 0)
{
blob = await UploadAndSaveBlobAsync(imageFile);
ad.ImageURL = blob.Uri.ToString();
}
El código que no se carga se encuentra en el método UploadAndSaveBlobAsync
. Crea un nombre GUID para el blob, carga y guarda el archivo y devuelve una referencia al blob guardado.
private async Task<CloudBlockBlob> UploadAndSaveBlobAsync(HttpPostedFileBase imageFile)
{
string blobName = Guid.NewGuid().ToString() + Path.GetExtension(imageFile.FileName);
CloudBlockBlob imageBlob = imagesBlobContainer.GetBlockBlobReference(blobName);
using (var fileStream = imageFile.InputStream)
{
await imageBlob.UploadFromStreamAsync(fileStream);
}
return imageBlob;
}
Después de que el método Create
HttpPost carga un blob y actualiza la base de datos, crea un mensaje de cola para informar a ese proceso back-end que una imagen está preparada para su conversión en una miniatura.
string queueMessageString = ad.AdId.ToString();
var queueMessage = new CloudQueueMessage(queueMessageString);
await queue.AddMessageAsync(queueMessage);
El código para el método Edit
HttpPost es similar con la excepción de que si el usuario selecciona un archivo de imagen nuevo, cualquier blob que ya exista se debe eliminar.
if (imageFile != null && imageFile.ContentLength != 0)
{
await DeleteAdBlobsAsync(ad);
imageBlob = await UploadAndSaveBlobAsync(imageFile);
ad.ImageURL = imageBlob.Uri.ToString();
}
En el siguiente ejemplo se muestra el código que elimina blobs cuando elimina un anuncio.
private async Task DeleteAdBlobsAsync(Ad ad)
{
if (!string.IsNullOrWhiteSpace(ad.ImageURL))
{
Uri blobUri = new Uri(ad.ImageURL);
await DeleteAdBlobAsync(blobUri);
}
if (!string.IsNullOrWhiteSpace(ad.ThumbnailURL))
{
Uri blobUri = new Uri(ad.ThumbnailURL);
await DeleteAdBlobAsync(blobUri);
}
}
private static async Task DeleteAdBlobAsync(Uri blobUri)
{
string blobName = blobUri.Segments[blobUri.Segments.Length - 1];
CloudBlockBlob blobToDelete = imagesBlobContainer.GetBlockBlobReference(blobName);
await blobToDelete.DeleteAsync();
}
ContosoAdsWeb - Views\Ad\Index.cshtml y Details.cshtml
El archivo Index.cshtml muestra miniaturas con otros datos de anuncio.
<img src="@Html.Raw(item.ThumbnailURL)" />
El archivo Details.cshtml muestra la imagen a tamaño completo.
<img src="@Html.Raw(Model.ImageURL)" />
ContosoAdsWeb - Views\Ad\Create.cshtml y Edit.cshtml
Los archivos Create.cshtml y Edit.cshtml especifican una codificación de formularios que permite al controlador obtener el objeto HttpPostedFileBase
.
@using (Html.BeginForm("Create", "Ad", FormMethod.Post, new { enctype = "multipart/form-data" }))
Un elemento <input>
indica al explorador que proporcione un cuadro de dialogo de selección.
<input type="file" name="imageFile" accept="image/*" class="form-control fileupload" />
ContosoAdsWorker - WorkerRole.cs - Método OnStart
El entorno del rol de trabajo de Azure llama al método OnStart
en la clase WorkerRole
cuando el rol de trabajo se inicia, y llama al método Run
cuando el método OnStart
finaliza.
El método OnStart
obtiene la cadena de conexión de base de datos del archivo .cscfg y la pasa a la clase DbContext de Entity Framework. El proveedor SQLClient se usa de forma predeterminada, por lo que no es necesario especificar el proveedor.
var dbConnString = CloudConfigurationManager.GetSetting("ContosoAdsDbConnectionString");
db = new ContosoAdsContext(dbConnString);
Después, el método obtiene una referencia a la cuenta de almacenamiento y crea el contenedor de blobs y la cola si no existen. El código para ello es similar al que ya vio en el método Application_Start
del rol web.
ContosoAdsWorker - WorkerRole.cs - Método Run
El método Run
se llama cuando el método OnStart
finaliza su trabajo de inicialización. El método ejecuta un bucle infinito que busca nuevos mensajes de cola y los procesa cuando llegan.
public override void Run()
{
CloudQueueMessage msg = null;
while (true)
{
try
{
msg = this.imagesQueue.GetMessage();
if (msg != null)
{
ProcessQueueMessage(msg);
}
else
{
System.Threading.Thread.Sleep(1000);
}
}
catch (StorageException e)
{
if (msg != null && msg.DequeueCount > 5)
{
this.imagesQueue.DeleteMessage(msg);
}
System.Threading.Thread.Sleep(5000);
}
}
}
Después de cada iteración del bucle, si no se encuentra ningún mensaje de cola, el programa entra en estado de suspensión durante un segundo. Esto suspensión evita que el rol de trabajo incurra en costos de tiempo de CPU y de transacción de almacenamiento excesivos. El equipo de asesoramiento al cliente de Microsoft cuenta una historia sobre un desarrollador que olvidó incluir esta función de suspensión, implementarla en producción y dejarla durante vacaciones. Cuando volvió, su descuido le costó algo más que las vacaciones.
Algunas veces, el contenido de un mensaje de cola causa un error de procesamiento. Este tipo de mensaje se denomina mensaje dudoso. Si simplemente registró un error y reinició el bucle, podría intentar procesar ese mensaje sin fin. Por lo tanto, el bloque catch incluye una instrucción if que comprueba cuántas veces la aplicación intentó procesar el mensaje actual. Si el recuento es superior a cinco veces, el mensaje se elimina de la cola.
ProcessQueueMessage
se llama cuando se encuentra un mensaje de cola.
private void ProcessQueueMessage(CloudQueueMessage msg)
{
var adId = int.Parse(msg.AsString);
Ad ad = db.Ads.Find(adId);
if (ad == null)
{
throw new Exception(String.Format("AdId {0} not found, can't create thumbnail", adId.ToString()));
}
CloudBlockBlob inputBlob = this.imagesBlobContainer.GetBlockBlobReference(ad.ImageURL);
string thumbnailName = Path.GetFileNameWithoutExtension(inputBlob.Name) + "thumb.jpg";
CloudBlockBlob outputBlob = this.imagesBlobContainer.GetBlockBlobReference(thumbnailName);
using (Stream input = inputBlob.OpenRead())
using (Stream output = outputBlob.OpenWrite())
{
ConvertImageToThumbnailJPG(input, output);
outputBlob.Properties.ContentType = "image/jpeg";
}
ad.ThumbnailURL = outputBlob.Uri.ToString();
db.SaveChanges();
this.imagesQueue.DeleteMessage(msg);
}
Este código lee la base de datos para obtener la dirección URL de la imagen, convierte la imagen en una miniatura, guarda la miniatura en un blob, actualiza la base de datos con la dirección URL del blob de la miniatura y elimina el mensaje de cola.
Nota:
El código del método ConvertImageToThumbnailJPG
usa clases del espacio de nombres System.Drawing por simplicidad. Sin embargo, las clases de este espacio de nombres se diseñaron para usarse con Windows Forms. No se admiten para usarse en un servicio de Windows o ASP.NET. Para más información acerca de las opciones de procesamiento de imagen, consulte Dynamic Image Generation (Generación de imagen dinámica) y Deep Inside Image Resizing (Profundización en el cambio de tamaño de imágenes).
Solución de problemas
En el caso de que algo no funcionen a pesar de seguir las instrucciones de este tutorial, aquí tiene algunos errores comunes y cómo resolverlos.
ServiceRuntime.RoleEnvironmentException
El objeto RoleEnvironment
lo proporciona Azure cuando se ejecuta una aplicación en Azure o cuando se ejecuta localmente mediante el emulador de proceso de Azure. Si aparece este error cuando la ejecución se realiza localmente, asegúrese establecer el proyecto ContosoAdsCloudService como el proyecto de inicio. Esta configuración hace que el proyecto se ejecute mediante el emulador de Proceso de Azure.
Una de las cosas para las que la aplicación usa RoleEnvironment de Azure es para conseguir valores de cadena de conexión almacenados en los archivos .cscfg , por lo que otra causa de esta excepción es la ausencia de una cadena de conexión. Asegúrese de que creó el valor StorageConnectionString para las configuraciones Nube y Local en el proyecto ContosoAdsWeb y que creó ambas cadenas de conexión para las dos configuraciones en el proyecto ContosoAdsWorker. Si busca StorageConnectionString mediante Buscar todo en toda la solución, verá que aparece nueve veces en seis archivos.
No se puede invalidar en el puerto xxx. El nuevo puerto está por debajo del valor mínimo permitido de 8080 para el protocolo http.
Intente cambiar el número de puerto usado por el proyecto web. Haga clic con el botón derecho en el proyecto ContosoAdsWeb y después seleccione Propiedades. Elija en la pestaña Web y después cambie el número de puerto en el valor URL del proyecto.
Para conocer otra alternativa que podría resolver el problema, consulte la sección siguiente.
Otros errores al realizar la ejecución localmente
De forma predeterminada, los nuevos proyectos de servicio en la nube usan el emulador de proceso de Azure rápido para simular el entorno de Azure. El emulador de Proceso de Azure es una versión ligera del emulador de proceso completo y, en algunas condiciones, el emulador completo funciona cuando la versión rápida no lo hace.
Para cambiar el proyecto para que use el emulador completo, haga clic con el botón derecho en el proyecto ContosoAdsCloudService y después seleccionePropiedades. En la ventana dePropiedades, seleccione la pestaña Web y, a continuación, seleccione el botón de radio Usar emulador completo.
Para ejecutar la aplicación con el emulador completo, tiene que abrir Visual Studio con privilegios de administrador.
Pasos siguientes
La aplicación Contoso Ads se hace intencionadamente sencilla para un tutorial de introducción. Por ejemplo, no implementa la inyección de dependencias ni los patrones de repositorio y unidad de trabajo. No utiliza una interfaz para el registro, no utiliza EF Code First Migrations para gestionar los cambios en el modelo de datos ni EF Connection Resiliency para gestionar los errores de red transitorios, etc.
Para obtener información general sobre el desarrollo para la nube, consulte Creación de aplicaciones del mundo real para la nube con Azure.
Para obtener más información, consulte los siguientes recursos: