2012-02-03 14 views
5

Ho un'applicazione Web ASP.NET 2.0 in parte navigata utilizzando i controlli DropDownList. Quando uno di questi viene modificato, causa un postback, che viene quindi reindirizzato a un altro URL in base a ciò che è stato selezionato nel menu a discesa.Postback ASP.NET da elenco a discesa errato dopo aver utilizzato il browser Pulsante Indietro

Ho notato un comportamento strano quando si utilizza il pulsante Indietro del browser dopo aver utilizzato i menu a discesa. La procedura è la seguente:

  1. Effettuare una selezione in uno dei menu a discesa, causando un postback e il reindirizzamento. Bene finora.
  2. Fare clic sul pulsante Indietro del browser.
  3. In un altro menu a discesa di spostamento inferiore a quello utilizzato prima dello (sono tutti contenuti in uno div), effettuare una selezione. La pagina reindirizza allo stesso URL la prima volta, non a ciò che dovrebbe reindirizzare in base a questo altro menu a discesa.

Ho provato questo sia in Firefox 10 e IE9 e visto la stessa cosa. Ho guardato la scheda Rete in Firebug e ho visto che nel POST del passaggio 3, viene fatto riferimento al controllo corretto. Ma quando eseguo il debug, il gestore di eventi per il dropdown errato (quello utilizzato nel passaggio 1) si attiva.

Il codice è abbastanza semplice e diretto. Esempio di marcatura:

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

I menu di scorrimento in realtà non sono semplici <asp:DropDownList ... /> elementi; Inserisco gli elementi optgroup con un approccio simile a this.

Esempio di C#:

ddlTest.Click += new EventHandler(ddlTest_SelectedIndexChanged); 

E in ddlTest_SelectedIndexChanged:

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

Che cosa sta succedendo qui?

AGGIORNAMENTO 2/6/2012: Ho risolto questo controllando per il contenuto di Request["__EVENTTARGET"] nei miei SelectedIndexChanged gestori di eventi. Sono ancora curioso di sapere perché succede, però. Perché il primo evento viene ripetuto? E perché succede solo quando il secondo postback avviene da un controllo sotto il primo?

+0

Puoi aggiungere i tag dalla pagina per i menu a discesa? Aiuterebbe. –

+0

I tag per i menu a discesa? Intendi i loro ID sulla pagina? O il loro markup? Sembra quasi il markup che ho postato nella domanda. –

+0

Solo un suggerimento: il tuo Nav non mostra quello che definirei comportamento previsto anche senza usare il pulsante Indietro. In genere, si suppone che nav sia sincronizzato con i tuoi contenuti. Ad esempio, quando fai clic sul nome di una scuola, quella scuola viene selezionata nell'elenco a discesa. In realtà, più lo guardo e più ci si sente * fuori *. Come se si potesse sbarazzarsi dell'intera nav sinistra (catturando quel bene immobile) e fornendo due drop down al vertice: scuola e sport. Gli altri sono completamente dipendenti da quelle informazioni comunque ... $ 0,02 per quello che vale. – NotMe

risposta

3

Dopo aver fatto clic sul pulsante Indietro, viene visualizzata l'ultima pagina visitata poiché viene salvata sul client non viene nuovamente inviata/richiesta nuovamente al/dal server, incluso l'ultimo valore pubblicato come la volta mostrata dopo aver selezionato il secondo DropDownlist subito dopo aver premuto il pulsante Indietro.

Il metodo onload su IE (per altri browser: http: //dean.edwards.name/weblog/2005/09/busted/) della prima pagina viene generato quando si preme il pulsante Indietro sul secondo usando questo possiamo provare a salvare sul client l'azione di postback prima di reindirizzare la pagina, la salviamo su un valore nascosto con JS, quindi una volta che l'utente torna indietro i metodi onload valutano se il nascosto ha un valore e se così cambia la posizione della pagina in modo che la pagina venga nuovamente richiesta e tutti i valori registrati vengano cancellati:

page1.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

è possibile utilizzare le proprietà ResponseCache per risolvere questo problema, in quanto si consente di memorizzare nella cache l'elenco in memoria del browser. da MSDN SetAllowResponseInBrowserHistory

Quando HttpCacheability è impostato NoCache o ServerAndNoCache il scadenza intestazione HTTP è che per impostazione predefinita -1; ciò indica al client non di memorizzare nella cache le risposte nella cartella Cronologia, in modo che quando si utilizzano i pulsanti back/forward il client richieda ogni volta una nuova versione della risposta . È possibile ignorare questo comportamento chiamando il metodo SetAllowResponseInBrowserHistory con il set di parametri allow su true.

nel metodo di caricamento della pagina, si aggiunge questa riga.

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"; 
    } 

in modo che ogni volta che si preme indietro, t richiederà ogni volta una nuova versione della risposta.

+0

Sembra una buona soluzione. Ho aggiornato la domanda per chiarire le informazioni che sto cercando. –

+0

Ho provato ad aggiungere le prime due linee al mio Page_Load e il problema si verifica ancora. –

3

Firefox - Aggiungere codice sottostante:

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

Chrome - Aggiungi javascript pageload:

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

Una leggera variazione sul risposta da @Ravi ha lavorato per me ...

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); 

    .... 
} 
Problemi correlati