Windows Azure y Classic Pipeline (Segunda Parte)

En la primera parte, vimos los requisitos que teníamos que cumplir para poder ejecutar una aplicación web diseñada para IIS 6.0 en un IIS 7.0 ó 7.5, y por ende, para poderla ejecutar en Windows Azure. El principal requisito es que la aplicación pueda utilizar el Modo Clásico del pipeline de .NET.

El único inconveniente de la solución aportada en la primera parte es que sólo es apta para aplicación que utilicen la versión de .NET 2.0/3.5.

Al ejecutar una aplicación en .NET 4.0 y que además utilice el pipeline clásico, nos encontraremos con un error 404 (File or directory not found), que la verdad, nos puede dejar un poco descolocados:

image

Como casi no nos lo podemos creer, nos vamos al servidor y vemos que el error tiene un pequeño matiz, el error es un 404.2:

image

Vemos que el problema está relacionado con el ISAPI que maneja las peticiones ASPX. Buscando literatura vemos que la raíz del problema es que, por defecto, el filtro ISAPI para .NET 4.0 no está activado por defecto. Podemos verlo en la siguiente imagen:

image

Bueno, una vez diagnosticado el problema sólo tenemos que buscar la manera de poder habilitar el filtro ISAPI para .NET 4.0 de manera automática (cómo ya explicamos en la primera parte, al tratarse de Azure no podemos realizar las configuraciones manualmente).

Buscando buscando, encontré la manera de modificar la sección de configuración de IIS que gestiona los filtros ISAPI (<isapiFilters>) y preparé un nuevo método dentro de nuestra clase RoleEntryPoint para establecer la configuración necesaria, el método AllowAspNet4Isapi:

 Private Sub AllowAspNet4Isapi()
     Trace.WriteLine("AllowAspNet4ISAPI...")
     Dim serverManager As ServerManager = New ServerManager
     Try
         Dim config As Configuration = ServerManager.GetApplicationHostConfiguration
  
         Dim isapiCgiRestrictionSection As ConfigurationSection = config.GetSection("system.webServer/security/isapiCgiRestriction")
         Dim isapiCgiRestrictionCollection As ConfigurationElementCollection = isapiCgiRestrictionSection.GetCollection
         Dim elems = isapiCgiRestrictionCollection.Where(Function(ce) ce.Attributes("description").Value = "ASP.NET v4.0.30319")
         For Each e As ConfigurationElement In elems
             Trace.WriteLine("Accessing to set 'allowed'=true...")
             e.Attributes("allowed").Value = True
         Next
  
         serverManager.CommitChanges()
     Catch ex As Exception
         Trace.WriteLine("Se ha producido un error: " + ex.Message)
         Trace.WriteLine("Exception: " + ex.ToString())
     Finally
         serverManager.Dispose()
     End Try
 End Sub

Con este nuevo método y un pequeño refactoring, OnStart() queda como sigue:

 Public Overrides Function OnStart() As Boolean
     'Configure Azure Tracing
     ConfigureTracing()
     'Permitir el ISAPI de .NET 4.0
     AllowAspNet4Isapi()
     'Configure Azure Pipeline
     SetClassicIISPipelineMode()
     Return MyBase.OnStart()
 End Function

Espero que os sea de utilidad, aunque repitiendo lo ya dicho en la primera parte, mi recomendación personal es actualizar la aplicación para poder ejecutarla utilizando el modo integrado, que tiene bastantes ventajas sobre el clásico (ref1, ref2).