Una de las novedades del Sdk 1.3 de Windows Azure es el soporte completo a Internet Information Server (Full IIS), que permite disponer de todas las característica de IIS en Windows Azure.
Antes de la salida de esta versión, Windows Azure ya disponía de WebRoles que podían exponer endpoints HTTP.
Windows Azure para realizar esta labor no empleaba un IIS, por lo que no podíamos hacer uso de todas las características que este producto ofrece; directorios virtuales, múltiples sites, exponer múltiples endpoints, endpoints TCP etc…
Windows Azure hacía uso del componente Hosted Web Core (HWC), que como su nombre indica, es en núcleo del IIS, por lo que ofrece las características más importantes de IIS, pero no todas. Seguramente en muchos escenarios con la funcionalidad ofrecida por HWC sería más que suficiente.
Por ejemplo, usando la versión completa del IIS podremos tener varios sites dentro del mismo webrole, podremos tener múltiples endpoint (HTTP/HTTP/TCP) sobre el mismo WebRoles, directorios y aplicaciones virtuales etc…
Desde el punto de vista de la arquitectura este diagrama muestra cómo es el comportamiento de la aplicación cuando se hace uso del HWC y cuando se hace uso de la versión completa del IIS.
A nivel funcional, sí que habrá pequeñas diferencias, como por ejemplo, que desde el WebEntryPoint no se tendrá acceso al fichero de configuración de la aplicación (web.config) si se está en el modo Full IIS.
Por defecto, cuando se crea un nuevo WebRole se empleará la versión completa del IIS, aunque si queremos podríamos configurarlo para que haga uso únicamente del HWC. De este modo el comportamiento sería el mismo que tenía un WebRole con la versión anterior del Sdk.
Si creamos una aplicación nueva y añadimos un WebRole, una de las primeras cosas que podremos ver es que en la configuración de los endpoint pueden configurarse tantos endpoints como se quiera, pudiendo elegir tres tipos de protocolos; HTTP, HTTPS o TCP. Con la versión anterior, un WebRole sólo podía tener dos endpoints como mucho, uno HTTP y otro HTTPS.
La siguiente peculiaridad la encontraremos en el fichero ServiceDefinition.csdef, que contendrá lo siguiente:
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SampleWebRole" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="WebRole">
<Sites>
<Site name="Web">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="80" />
</Endpoints>
<Imports>
<Import moduleName="Diagnostics" />
</Imports>
</WebRole>
</ServiceDefinition>
Fijaros en el XML anterior que éste contiene la definición de los sites que contiene el WebRole y los endpoints asociados. En este caso existe un único site asociado un endpoint http que emplea el puerto 80.
El site “Web” se considera que el site por defecto y es el único en el que no debe indicarse la propiedad “physicalDirectory”. Si por ejemplo le cambiamos el nombre al site tendremos que añadir dicha propiedad, para indicar la ruta física dónde se encuentra.
Las rutas son path relativos al fichero ServiceDefinition.csdef. (WebRole es el nombre que le he dado al role)
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SampleWebRole"
xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="WebRole">
<Sites>
<Site name="MyCustomWebSite" physicalDirectory="..WebRole">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="80" />
</Endpoints>
<Imports>
<Import moduleName="Diagnostics" />
</Imports>
</WebRole>
</ServiceDefinition>
Sobre este fichero podremos hacer las modificaciones que consideremos para añadir más sites, directorios virtuales o lo que consideremos. Los conceptos son los mismos que manejamos al trabajar con IIS.
Por ejemplo, en el XML siguiente se configura un WebRole con dos sites. Los dos sites se encuentras asociados al mismo endpoint.
Se ha uso de la propiedad “hostHeader” que site debe responder en cada momento. En función de la URL de la que venga la petición, contestará un site u otro…lógicamente, en este caso es el mismo.
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SampleWebRole"
xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="WebRole">
<Sites>
<Site name="MyFirstCustomWebSite" physicalDirectory="..WebRole">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="www.myfirstsite.com"/>
</Bindings>
</Site>
<Site name="MySecondCustomWebSite" physicalDirectory="..WebRole">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="www.mysecondsite.com" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="80" />
</Endpoints>
<Imports>
<Import moduleName="Diagnostics" />
</Imports>
</WebRole>
</ServiceDefinition>
Para poder probar en local este escenario es necesario modificar el fichero “host” de vuestro equipo, para que las URLs configuradas en el hostHeader apunten a la dirección 127.0.0.1.
Una vez configurado este escenario y si damos a F5 en Visual Studio, encontraremos el siguiente error: “HTTP 400 Bad Request”.
El problema es que al haber cambiado la configuración por defecto, Visual Studio y el Compute Emulator no son capaces de encontrar el site por defecto que debe resolver la petición. Es por este motivo por el que toca realizar más cambios…
Si abrimos la herramienta del configuración del IIS (con el modo depuración de Visual Studio arrancado) veremos que tenemos 2 sites temporales como los siguientes: (uno por cada site de la aplicación)
Tenemos que cambiar el binding de estos sites para que apunten a un puerto válido..y que no se esté usando!! Si ponemos www.myfirstsite.com:8081 en el navegador ya tendremos la aplicación contestando peticiones.
Para seguir viendo más características he añadido un nuevo proyecto a la solución de tipo WebApplication. No es un nuevo WebRole, es simplemente un nuevo proyecto web llamado SecondWebApp.
Podemos configurar cada site para que apunte a un proyecto diferente:
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SampleWebRole"
xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="WebRole">
<Sites>
<Site name="MyFirstCustomWebSite" physicalDirectory="..SecondWebApp">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="www.myfirstsite.com"/>
</Bindings>
</Site>
<Site name="MySecondCustomWebSite" physicalDirectory="..WebRole">
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="www.mysecondsite.com" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="80" />
</Endpoints>
<Imports>
<Import moduleName="Diagnostics" />
</Imports>
</WebRole>
</ServiceDefinition>
Y si ejecutamos la aplicación (F5), veremos que en función de la URL que pongamos en el navegador contestará una aplicación u otra.
Otra posibilidad que tenemos es la de crear directorios o aplicaciones virtuales. En este ejemplo se ve cómo crear una aplicación virtual dentro de un site.
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SampleWebRole"
xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="WebRole">
<Sites>
<Site name="Web" physicalDirectory="..WebRole">
<VirtualApplication name="SecondApp" physicalDirectory="..SecondWebApp"></VirtualApplication>
<Bindings>
<Binding name="Endpoint1" endpointName="Endpoint1"/>
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="Endpoint1" protocol="http" port="80" />
</Endpoints>
<Imports>
<Import moduleName="Diagnostics" />
</Imports>
</WebRole>
</ServiceDefinition>
Y vemos como poniendo la URL base me sale la aplicación principal y cómo si ponemos la URL de la aplicación virtual me responde la segunda aplicación.
En la URL añado el nombre de la aplicación virtual.
Espero que os haya sido de utilidad!