Hospedar ASP.NET Web API 2 en un rol de trabajo de Azure

por Mike Wasson

En este tutorial se muestra cómo hospedar ASP.NET API web en un rol de trabajo de Azure, mediante OWIN para hospedar automáticamente el marco de API web.

Open Web Interface for .NET (OWIN) define una abstracción entre servidores web .NET y aplicaciones web. OWIN desacopla la aplicación web del servidor, lo que hace que OWIN sea ideal para el autohospedaje de una aplicación web en su propio proceso, fuera de IIS, por ejemplo, dentro de un rol de trabajo de Azure.

En este tutorial, usará el paquete Microsoft.Owin.Host.HttpListener, que proporciona un servidor HTTP que se usa para hospedar aplicaciones OWIN autohospedar.

Versiones de software usadas en el tutorial

Creación de un proyecto de Microsoft Azure

Inicie Visual Studio con privilegios de administrador. Los privilegios de administrador son necesarios para depurar la aplicación localmente mediante el emulador de proceso de Azure.

En el menú Archivo, haga clic en Nuevo y, después, haga clic en Proyecto. En Plantillas instaladas, en Visual C#, haga clic en Nube y, a continuación, en Servicio de nube de Windows Azure. Asigne al proyecto el nombre "AzureApp" y haga clic en Aceptar.

Screenshot of the 'new project' dialog box, highlighting the steps in the menu options to create an Azure App project.

En el cuadro de diálogo Nuevo servicio de nube de Windows Azure, haga doble clic en Rol de trabajo. Deje el nombre predeterminado ("WorkerRole1"). Este paso agrega un rol de trabajo a la solución. Haga clic en OK.

Screenshot of the 'New Windows Azure Cloud Service' dialog box, showing the menu options to create a worker role.

La solución de Visual Studio que se crea contiene dos proyectos:

  • "AzureApp" define los roles y la configuración de la aplicación de Azure.
  • "WorkerRole1" contiene el código para el rol de trabajo.

En general, una aplicación de Azure puede contener varios roles, aunque en este tutorial se usa un solo rol.

Screenshot of the solution explorer window, highlighting the new Azure App project and showing the app name and worker role option below it.

Adición de la API web y los paquetes OWIN

En el menú Herramientas, haga clic en Administrador de paquetes NuGet y luego en Consola del Administrador de paquetes.

En la ventana Consola del Administrador de paquetas , escriba el siguiente comando:

Install-Package Microsoft.AspNet.WebApi.OwinSelfHost

Agregar un punto de conexión HTTP

En el Explorador de soluciones, expanda el proyecto AzureApp. Expanda el nodo Roles, haga clic con el botón derecho en WorkerRole1 y seleccione Propiedades.

Screenshot of the solution explorer window menu, highlighting the steps to select the worker role's property settings.

Haga clic en Puntos de conexión y, después, en Agregar punto de conexión.

En la lista desplegable Protocolo, seleccione "http". En Puerto público y Puerto privado, escriba 80. Estos números de puerto pueden ser diferentes. El puerto público es lo que usan los clientes cuando envían una solicitud al rol.

Screenshot of the protocol dropdown menu options that show the different service configurations and endpoint choices.

Configuración de la API web para autohospedaje

En el Explorador de soluciones, haga clic con el botón derecho en el proyecto WorkerRole1 y seleccione Agregar / Clase para agregar una nueva clase. Asigne Startup como nombre de la clase.

Screenshot of the solution explorer window, showing the menu options and highlighting the path to adding a class.

Reemplace todo el código reutilizable de este archivo por:

using Owin;
using System.Web.Http;

namespace WorkerRole1
{
    class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            HttpConfiguration config = new HttpConfiguration();
            config.Routes.MapHttpRoute(
                "Default",
                "{controller}/{id}",
                new { id = RouteParameter.Optional });

            app.UseWebApi(config);
        }
    }
}

Añadir un controlador de API web

A continuación, agregue una clase de controlador de API web. Haga clic con el botón derecho en el proyecto WorkerRole1 y seleccione Agregar / Clase. Asigne un nombre a la clase TestController. Reemplace todo el código reutilizable de este archivo por:

using System;
using System.Net.Http;
using System.Web.Http;

namespace WorkerRole1
{
    public class TestController : ApiController
    {
        public HttpResponseMessage Get()
        {
            return new HttpResponseMessage()
            {
                Content = new StringContent("Hello from OWIN!")
            };
        }

        public HttpResponseMessage Get(int id)
        {
            string msg = String.Format("Hello from OWIN (id = {0})", id);
            return new HttpResponseMessage()
            {
                Content = new StringContent(msg)
            };
        }
    }
}

Para simplificar, este controlador simplemente define dos métodos GET que devuelven texto sin formato.

Iniciar el host OWIN

Abra el archivo WorkerRole.cs. Esta clase define el código que se ejecuta cuando se inicia y detiene el rol de trabajo.

Agregue la siguiente instrucción using:

using Microsoft.Owin.Hosting;

Agregue un miembro IDisposable a la clase WorkerRole:

public class WorkerRole : RoleEntryPoint
{
    private IDisposable _app = null;

    // ....
}

En el método OnStart, agregue el código siguiente para iniciar el host:

public override bool OnStart()
{
    ServicePointManager.DefaultConnectionLimit = 12;

    // New code:
    var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["Endpoint1"];
    string baseUri = String.Format("{0}://{1}", 
        endpoint.Protocol, endpoint.IPEndpoint);

    Trace.TraceInformation(String.Format("Starting OWIN at {0}", baseUri), 
        "Information");

    _app = WebApp.Start<Startup>(new StartOptions(url: baseUri));
    return base.OnStart();
}

El método WebApp.Start inicia el host OWIN. El nombre de la clase Startup es un parámetro de tipo para el método. De forma predeterminada, el host llamará al método Configure de esta clase.

Invalide OnStop para eliminar la instancia _app:

public override void OnStop()
{
    if (_app != null)
    {
        _app.Dispose();
    }
    base.OnStop();
}

Este es el código completo para WorkerRole.cs:

using Microsoft.Owin.Hosting;
using Microsoft.WindowsAzure.ServiceRuntime;
using System;
using System.Diagnostics;
using System.Net;
using System.Threading;

namespace WorkerRole1
{
    public class WorkerRole : RoleEntryPoint
    {
        private IDisposable _app = null;

        public override void Run()
        {
            Trace.TraceInformation("WebApiRole entry point called", "Information");

            while (true)
            {
                Thread.Sleep(10000);
                Trace.TraceInformation("Working", "Information");
            }
        }

        public override bool OnStart()
        {
            ServicePointManager.DefaultConnectionLimit = 12;

            var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["Endpoint1"];
            string baseUri = String.Format("{0}://{1}", 
                endpoint.Protocol, endpoint.IPEndpoint);

            Trace.TraceInformation(String.Format("Starting OWIN at {0}", baseUri), 
                "Information");

            _app = WebApp.Start<Startup>(new StartOptions(url: baseUri));
           return base.OnStart();
        }

        public override void OnStop()
        {
            if (_app != null)
            {
                _app.Dispose();
            }
            base.OnStop();
        }
    }
}

Compile la solución y presione F5 para ejecutar la aplicación localmente en el emulador de proceso de Azure. En función de la configuración del firewall, es posible que tenga que permitir el emulador a través del firewall.

Nota:

Si recibe una excepción como la siguiente, consulte esta entrada de blog para obtener una solución alternativa. "No se puede cargar el archivo o ensamblado 'Microsoft.Owin.Security, Version=2.0.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' ni una de sus dependencias. La definición de manifiesto del ensamblado ubicado no coincide con la referencia del ensamblado. (Excepción de HRESULT: 0x80131040)"

El emulador de proceso asigna una dirección IP local al punto de conexión. Para encontrar la dirección IP, consulte la interfaz de usuario del emulador de proceso. Haga clic con el botón derecho en el icono del emulador en el área de notificación de la barra de tareas y seleccione Mostrar interfaz de usuario del emulador de proceso.

Screenshot of the Azure Compute Emulator U I, showing the menu and the I P endpoint address information, when selecting the 'service details' option.

Busque la dirección IP en Implementaciones de servicio, [id] de implementación, Detalles del servicio. Abra un explorador web y vaya a http://address/test/1, donde address es la dirección IP asignada por el emulador de proceso; por ejemplo, http://127.0.0.1:80/test/1. Debería ver la respuesta del controlador de API web:

Screenshot of the browser window showing the Web A P I controller response after inputting the I P address assigned by the compute emulator.

Implementación en Azure

Para este paso, debe tener una cuenta de Azure. Si aún no tiene una, puede crear una cuenta de evaluación gratuita en un par de minutos. Para más información, consulte Evaluación gratuita de Microsoft Azure.

En el Explorador de soluciones, haga clic con el botón derecho en el proyecto AzureApp. Seleccione Publicar.

Screenshot of the solution explorer window's menu options, which highlights the steps to follow in order to deploy or publish the project.

Si no ha iniciado sesión en su cuenta de Azure, haga clic en Iniciar sesión.

Screenshot of the 'publish Azure application' dialog box, which requests a sign in option before other options become available.

Después de iniciar sesión, elija una suscripción y haga clic en Siguiente.

Screenshot of the 'publish Azure application' after sign in, prompting user to choose a subscription type before continuing to the next step.

Escriba un nombre para el servicio en la nube y elija una región. Haga clic en Crear.

Screenshot of the 'create cloud service and storage account' dialog box, requesting user to enter a name and region for their application's service.

Haga clic en Publicar.

Screenshot of the 'publish Azure application' window, confirming all of the settings selections made, and providing button options to go back or publish.

Configuración de un nombre de dominio personalizado para un servicio en la nube de Azure (clásico)

Recursos adicionales