2012-02-03 12 views
5

Tengo una aplicación web ASP.NET 2.0 que se navega parcialmente usando los controles DropDownList. Cuando se modifica uno de ellos, provoca una devolución de datos, que luego se redirige a otra URL según lo que se eligió en el menú desplegable.Postback de ASP.NET desde una lista desplegable incorrecta después de usar el botón Atrás del navegador

He notado un comportamiento extraño al usar el botón Atrás del navegador después de usar las listas desplegables. El procedimiento es el siguiente:

  1. Realice una selección en uno de los menús desplegables, generando una devolución de datos y redirigiendo. Bien hasta ahora.
  2. Haga clic en el botón Atrás del navegador.
  3. En otro menú desplegable de navegación debajo del utilizado antes de (están todos contenidos en un div), haga una selección. La página redirige a la misma URL que la primera vez, no a la que debería redireccionar según este otro menú desplegable.

He intentado esto tanto en Firefox 10 como en IE9 y he visto lo mismo. Miré la pestaña Red en Firebug y vi que en el POST para el paso 3, se hace referencia al control correcto. Pero cuando lo depuro, se desencadena el controlador de eventos para el menú desplegable incorrecto (el utilizado en el paso 1).

El código es bastante simple y directo. Ejemplo de marcado:

<asp:DropDownList runat="server" ID="ddlTest" AutoPostBack="true" /> 

Los menús desplegables en realidad no son sencillas <asp:DropDownList ... /> elementos; Estoy insertando elementos optgroup con un enfoque similar a this.

Ejemplo de C#:

ddlTest.Click += new EventHandler(ddlTest_SelectedIndexChanged); 

Y en ddlTest_SelectedIndexChanged:

if (ddlTest.SelectedValue != "") 
{ 
    Response.Redirect(MyUtilClass.GetUrl(ddlTest.SelectedValue)); 
} 

¿Qué está pasando aquí?

ACTUALIZACIÓN 2/6/2012: Me he fijado mediante la comprobación del contenido de Request["__EVENTTARGET"] en mis SelectedIndexChanged controladores de eventos. Todavía tengo curiosidad de por qué sucede, sin embargo. ¿Por qué se repite el primer evento? ¿Y por qué solo ocurre cuando la segunda devolución de datos ocurre desde un control debajo del primero?

+0

¿Puedes agregar las etiquetas de la página para las listas desplegables? Ayudaría. –

+0

Las etiquetas para las listas desplegables? ¿Te refieres a sus identificaciones en la página? ¿O su marcado? Se parece mucho al marcado que publiqué en la pregunta. –

+0

Solo una sugerencia: su Nav no muestra lo que llamaría comportamiento esperado incluso sin utilizar el botón Atrás. Por lo general, se supone que la navegación se sincroniza con su contenido. De modo que cuando haga clic en el nombre de una escuela, esa escuela se seleccionará en su menú desplegable. En realidad, cuanto más lo veo, más se siente * apagado *. Como si pudieras deshacerte de todo el sistema de navegación izquierdo (capturando ese inmueble de vuelta) y proporcionar dos menús desplegables en la parte superior: la escuela y el deporte. Los demás dependen completamente de esa información de todos modos ... $ 0.02 por lo que vale. – NotMe

Respuesta

3

Una vez que haga clic en el botón Atrás, se mostrará la última página visitada, ya que se guarda en el cliente y no se envía/solicita nuevamente al servidor, incluyendo el último valor publicado como el mostrado una vez seleccionado la segunda DropDownlist justo después de presionar el botón Atrás.

El método de carga en IE (para otros navegadores, vea: http: //dean.edwards.name/weblog/2005/09/busted/) de la primera página se activa cuando presiona el botón Atrás en el segundo Usando esto podemos tratar de guardar en el cliente la acción de devolución de datos antes de redirigir la página, la guardamos en un valor oculto con JS, luego, una vez que el usuario retrocede, los métodos de carga evalúan si el oculto tiene un valor y, si es así, cambias la ubicación de la página para que la página se solicite nuevamente y se borren todos los valores publicados:

página1.aspx

<script type="text/javascript"> 
     function redir(){  
      var h=document.getElementById('hdR'); 
      if (h.value=='1'){ 
       h.value='0'; 
       document.location.href='page1.aspx'; 
      }   
     } 

     function changeHids(){ 
      var h=document.getElementById('hdR'); 
      h.value='1'; 
     } 
     </script> 
    </head> 
    <body onload="redir();"> 
     <form id="form1" runat="server"> 
     <div> 
      <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true" onchange="changeHids();"> 
       <asp:ListItem>1</asp:ListItem> 
       <asp:ListItem>2</asp:ListItem> 
       <asp:ListItem>3</asp:ListItem> 
       <asp:ListItem>4</asp:ListItem> 
      </asp:DropDownList> 
      <br /> 
      <asp:DropDownList ID="DropDownList2" runat="server" AutoPostBack="true" onchange="changeHids();"> 
       <asp:ListItem>5</asp:ListItem> 
       <asp:ListItem>6</asp:ListItem> 
       <asp:ListItem>7</asp:ListItem> 
       <asp:ListItem>8</asp:ListItem> 
      </asp:DropDownList> 
      <asp:HiddenField ID="hdR" runat="server"/> 
     </div> 
     </form> 
    </body> 

Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropDownList1.SelectedIndexChanged 

    Response.Redirect("page2.aspx?ddl=1&val=" & Me.DropDownList1.SelectedValue, True) 

End Sub 

Protected Sub DropDownList2_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropDownList2.SelectedIndexChanged 

    Response.Redirect("page2.aspx?ddl=2&val=" & Me.DropDownList2.SelectedValue, True) 

End Sub 

page2.aspx

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 

     Response.Write("ddl:" & Request.QueryString("ddl") & " " & "value:" & Request.QueryString("val")) 

    End Sub 
2

puede utilizar las propiedades Response.Cache para resolver este problema, ya que está permitiendo almacenar en caché la lista en la memoria del navegador. de MSDN SetAllowResponseInBrowserHistory

Cuando HttpCacheability se establece en NoCache o ServerAndNoCache la Expira cabecera HTTP es por defecto se establece en -1; esto le dice al cliente no que guarde las respuestas en la carpeta Historial, para que cuando use los botones atrás/adelante, el cliente solicite una nueva versión de la respuesta cada vez. Puede anular este comportamiento llamando al método SetAllowResponseInBrowserHistory con el parámetro allow en true.

en su método de carga de página, agrega esta línea.

protected void Page_Load(object sender, EventArgs e) 
    { 
     Response.Cache.SetCacheability(HttpCacheability.NoCache); 
     Response.Cache.SetAllowResponseInBrowserHistory(false); 

     // or else you can do like this 

     Response.ExpiresAbsolute = DateTime.Now.AddDays(-1d); 
     Response.Expires = -1; 
     Response.CacheControl = "No-cache"; 
    } 

de manera que cada vez que se presiona la espalda, t se solicita una nueva versión de la respuesta cada vez.

+0

Esto parece una buena solución. He actualizado la pregunta para aclarar la información que estoy buscando. –

+0

Intenté agregar las dos primeras líneas a mi Page_Load, y el problema aún ocurre. –

3

Firefox - Añadir código subyacente:

protected void Page_Load(object sender, EventArgs e) 
{ 
    Response.AppendHeader("Cache-Control", "no-store"); 
} 

Chrome - Añadir Javascript pageload:

var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1; 
if (is_chrome) { 
    document.getElementById("form1").reset(); 
} 
0

Una ligera variación en la respuesta de @Ravi funcionó para mí ...

protected override void OnInit(EventArgs e) 
{ 
    base.OnInit(e); 

    Context.Response.AddHeader("Cache-Control", "max-age=0,no-cache,no-store"); 
    Context.Response.Cache.SetCacheability(HttpCacheability.NoCache); 
    Context.Response.Cache.SetMaxAge(TimeSpan.Zero); 

    .... 
} 
Cuestiones relacionadas