Imagen ornamentalBueno, esto es tecnología viejuna pero que está en uso en miles (o millones) de Web de todo el mundo, incluyendo este blog en el momento de escribir esto en 2020. La maravillosa tecnología ASP.NET Web Forms fue un invento de Scott Guthrie (sí, ese Scott del polo rojo que manda tanto en Microsoft y parece un tipo tan majo) que permitía crear aplicaciones Web orientadas a datos aunque no tengas mucha idea de la Web. Y de hecho aún lo permite, viene incluida de serie en Windows junto con la plataforma .NET, y sigue siendo muy interesante para ciertos tipos de aplicaciones.

Precisamente lo mejor que tiene, es también lo peor: es tan fácil crear algunas aplicaciones sin entender bien qué está ocurriendo que luego "pasan cosas". Esta tecnología se basa en la inclusión de un formulario envolviendo toda la página, que además tiene que ser único, y que ante cualquier acción se envía al servidor y vuelve a la misma página (postback), transfiriendo entre llamadas unos datos llamados ViewState que, como su propio nombre indica, contienen el estado de la página. Este ViewState si no lo controlas puede llegar a pesar muchísimo y a ralentizar las páginas, pero se puede y se debe controlar si conoces bien la tecnología. Más adelante le añadieron soporte para llamadas AJAX de modo que ni siquiera la página tenía que recargarse, para lo cual introdujeron el ScriptManager y el UpdatePanel, dos piezas clave de esta tecnología.

Bien, el caso es que hay un efecto secundario del uso de estas tecnologías que puede volverte loco, aunque no se da con frecuencia. Si utilizas algún tipo de hash en tu URL (esas direcciones que terminan en un # con algo a continuación y que sirven para navegación interna en la página) de modo que permitas saltar directamente a alguna parte de la página, tanto los Web Forms "puros" como los UpdatePanel para AJAX se lo cargan.

El típico ejemplo es una página con varios "tabs" para mostrar información diferente según el que pulses. Puedes cambiar  de uno a otro pulsando en las cabeceras y mantienes cuál es el que está abierto simplemente anotando el identificador con un hash: mipagina.aspx#tab1 y similares.

Bien, el problema es que al actualizar la página con un UpdatePanel, ese #tab1 desaparece, y no puedes mantener la interfaz en donde estaba: te va a cambiar el hash y te dejará tan solo un #, moviéndote la página para arriba del todo, por lo que si tus tabs estaban hacia abajo, pierdes el estado del scroll también. Un horror.

¿Cómo lo solucionamos?

El problema lo produce una función de la infraestructura del Update Panel que se llama _setState y cuyo código es el que se ve en esta figura:

El código del método _setState

Este código por algún motivo toquetea el contenido de la URL actual y en concreto su hash. Sinceramente no tengo ni idea de lo que hace ni he logrado encontrar por ahí información, ya que es código no documentado e interno de cómo funcionan el ScriptManager y el UpdatePanel, pero por lo que se ve es alguna manera de guardar un histórico de interacciones con el panel o algo así. En la práctica, sinceramente, no parece que haga nada útil.

Si para nuestra página es importante que se conserve el hash que hemos puesto tenemos dos opciones:

  1. Redefinir ese método metiendo una comprobación al principio de modo que si hay un hash en nuestra dirección, directamente que no haga nada.
  2. Ir "a saco" y directamente redefinir el método para cargártelo y que no haga nada.

Yo, las veces que me ha pasado (una de ellas muy reciente) lo que he hecho ha sido ir por la segunda opción, que e la vía fácil. Y no he notado problema alguno para poder utilizar las páginas cambiadas con total normalidad. Pienso que el script hace efecto e ocasiones muy poco frecuentes y que no pasa nada por eliminarlo. Pero tienes que probarlo en tu caso concreto.

El código para eliminarlo es muy sencillo. Simplemente tienes que poner esta línea en un script posterior al del ScriptManager:

Sys._Application.prototype._setState = function(){};

Vamos, que directamente le asignas una función vacía, que no hace nada de nada. Así, a lo bestia.

Esto puede ir simplemente en un script justo antes de cerrar el body de la página o bien en el evento DOMContentLoaded de la página o la función $() de jQuery si estás usando esta biblioteca. Lo dejo a tu elección.

Tu página no volverá a perder el hash.

¡Espero que te resulte útil!

Escrito por un humano, no por una IA