Reescritura de direcciones URL para ASP.NET Web Forms
por Ruslan Yakushev
Cuando se usa el módulo Reescritura de direcciones URL de IIS con aplicaciones de ASP.NET, es importante garantizar el comportamiento correcto de la aplicación web con direcciones URL reescritas. En este artículo se explican los escenarios en los que la reescritura de direcciones URL puede afectar a aplicaciones web ASP.NET y las soluciones a posibles problemas.
Tabla de contenido
- Establecimiento de la dirección URL de postback para el elemento form
- Reescritura de direcciones URL para el control UpdatePanel de AJAX
- Uso del operador "~" en controles de servidor web
- Reescritura de direcciones URL y controles de navegación del sitio
- Prevención de la reescritura de solicitudes para recursos de ASP.NET
Establecimiento de la dirección URL de postback para el elemento form
ASP.NET Web Forms usa postbacks de forma generalizada, y esto hace que sea algo complicado realizar la reescritura de direcciones URL para las páginas de ASP.NET. Si la página contiene uno o varios controles de servidor web, cuando ASP.NET representa la página, establece el atributo de acción del elemento de formulario HTML para que apunte a la página donde está el elemento de formulario, es decir, apunta a sí mismo. Si se usa la reescritura de direcciones URL para esa página, el atributo de acción apunta a la dirección URL reescrita, no a la dirección URL solicitada desde el explorador. Esto hace que el explorador muestre la dirección URL reescrita en el cuadro de direcciones cada vez que se produzca un postback.
Para evitar que el atributo de acción apunte a la dirección URL incorrecta, puede establecer la propiedad Action de la instancia de HtmlForm en la página en la dirección URL del postback que solicitó el explorador. Puede obtener esa dirección URL mediante la propiedad HttpRequest.RawUrl. En el ejemplo siguiente se muestra cómo puede modificar la página ASP.NET para establecer la dirección URL de la acción.
protected void Page_Load(object sender, EventArgs e)
{
form1.Action = Request.RawUrl;
}
Nota:
La propiedad HtmlForm.Action está disponible a partir de .NET Framework versión 3.5 SP1.
Si usa páginas maestras de ASP.NET, puede agregar código al método Page_Load de la página maestra a fin de establecer la dirección URL de acción de postback para todas las páginas que usan esa página maestra.
Reescritura de direcciones URL para el control UpdatePanel de AJAX
Cuando se usa el módulo Reescritura de direcciones URL a fin de volver a escribir la dirección URL de una página que contiene uno o varios controles UpdatePanel, el control usará la dirección URL reescrita para todas las acciones que realiza ese control UpdatePanel. Esto puede hacer que los controles del control UpdatePanel no funcionen correctamente, especialmente en los casos en los que la reescritura de direcciones URL cambia la jerarquía de directorios de la dirección URL solicitada. Por ejemplo, si usa el módulo Reescritura de direcciones URL para reescribir /Products/Hardware en /Products.aspx, el control UpdatePanel usará la dirección URL /Products/Hardware/Products.aspx para todas las acciones del control UpdatePanel. Esto produce un error de script.
Para evitar que esto suceda, establezca la propiedad Action de la instancia HtmlForm de la página tal como se describe en Establecimiento de la dirección URL de postback para el elemento form de la sección anterior.
Uso del operador "~" en controles de servidor web
Puede usar el operador ~ en controles de servidor web de ASP.NET para hacer referencia a la raíz del directorio de la aplicación cuando necesite establecer una ruta de acceso. Pero si la reescritura de direcciones URL cambia la jerarquía de directorios de la dirección URL solicitada, esto puede hacer que los vínculos especificados con el operador ~ se resuelvan incorrectamente. Por ejemplo, imagine que la página Default.aspx en la raíz de una aplicación web denominada app1 contiene el siguiente control Image:
<asp:Image runat="server" ImageUrl="~/Images/MyImage.gif" />
Si la reescritura de la dirección URL cambia la dirección URL de http://localhost/app1/folder/file
a http://localhost/app1/default.aspx
, los vínculos especificados con el operador ~ se resolverán en relación con la ruta de acceso de dirección URL reescrita, que estaría relacionada con la carpeta /app1. En el ejemplo siguiente se muestra el marcado HTML resultante para el elemento img:
<img src="Images/MyImage.gif" ... >
Dado que el explorador ha solicitado http://localhost/app1/folder/file
, intentará obtener la imagen de http://localhost/app1/folder/Images/MyImage.gif
. Esto da como resultado un error 404 (Archivo no encontrado).
El módulo reescritura de direcciones URL para IIS incluye una actualización de ASP.NET que corrige este comportamiento. La actualización hace que el operador ~ de los controles de servidor web se resuelva en relación con la dirección URL solicitada originalmente. En el ejemplo anterior, el marcado HTML de la respuesta contendrá la ruta de acceso de dirección URL correcta para el elemento img, como se muestra en el marcado siguiente:
<img src="../Images/MyImage.gif" ... >
La actualización de ASP.NET solo se aplica a .NET Framework 3.5 SP1 y versiones posteriores. Para obtener la actualización, actualice .NET Framework a la versión 3.5 SP1 y, después, ejecute el instalador del módulo Reescritura de direcciones URL de IIS, que instalará la actualización de ASP.NET.
Reescritura de direcciones URL y controles de navegación del sitio
Se puede usar un mapa del sitio ASP.NET a fin de describir la estructura de un sitio web para que la API de navegación del sitio y los controles de navegación del sitio puedan exponer una estructura de sitio lógica (en lugar de física). Cuando se usa el módulo Reescritura de direcciones URL con una aplicación de ASP.NET que usa la navegación del sitio, normalmente se quieren que los controles de navegación funcionen en términos de estructura de sitio lógico que usa direcciones URL públicas o virtuales.
Por ejemplo, podría definir un mapa del sitio como se muestra en el ejemplo siguiente:
<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0">
<siteMapNode url="~/Products/" title="Products" description="Products Home Page">
<siteMapNode url="~/Products/Hardware/" title="Hardware" description="Hardware Products" />
<siteMapNode url="~/Products/Software/" title="Software" description="Software Products" />
</siteMapNode>
</siteMap>
Después, puede definir reglas de reescritura que realicen las siguientes reescrituras:
- /Products/ a /Products.aspx
- /Products/Hardware a /Products.aspx?category=Hardware
- /Products/Software a /Products.aspx?category=Software
Definir un mapa del sitio mediante estas direcciones URL virtuales puede hacer que la clase SystemWeb.SiteMap no funcione correctamente. Al intentar acceder a la propiedad SiteMap.CurrentNode en una página de ASP.NET, la propiedad puede contener valores null. Esto puede hacer que los controles de navegación del sitio como SiteMapPath y Menu no funcionen correctamente.
El módulo Reescritura de direcciones URL para IIS incluye una actualización de ASP.NET que corrige los controles de navegación a fin de que puedan trabajar con direcciones URL virtuales que están reescritas. Con esta actualización, la propiedad SiteMap.CurrentNode hará referencia al elemento SiteMapNode que corresponde a la dirección URL virtual solicitada actualmente.
La actualización de ASP.NET solo se aplica a .NET Framework 3.5 SP1 y versiones posteriores. Para obtener la actualización, actualice .NET Framework a la versión 3.5 SP1 y, después, ejecute el instalador del módulo Reescritura de direcciones URL de IIS, que instalará la actualización de ASP.NET.
Prevención de la reescritura de solicitudes para recursos web de ASP.NET
Las aplicaciones web basadas en ASP.NET suelen realizar solicitudes al archivo WebResources.axd para recuperar los recursos de ensamblado y servirlos en el explorador web. No existe este archivo en el servidor porque ASP.NET genera el contenido de forma dinámica cuando se solicita WebResources.axd. Por lo tanto, si tiene una regla de reescritura de direcciones URL que realiza la reescritura o redirección solo si la dirección URL solicitada no corresponde a un archivo o una carpeta en el sistema de archivos de un servidor web, esa regla puede reescribir accidentalmente las solicitudes realizadas a WebResources.axd y, por tanto, interrumpir la aplicación.
Este problema se puede evitar fácilmente si agrega una condición adicional a la regla de reescritura:
<rule name="RewriteUserFriendlyURL1" stopProcessing="true">
<match url="^([^/]+)/?$" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<!-- The following condition prevents rule from rewriting requests to .axd files -->
<add input="{URL}" negate="true" pattern="\.axd$" />
</conditions>
<action type="Rewrite" url="article.aspx?p={R:1}" />
</rule>