2012-02-03 14 views
5

Tôi đã có một ứng dụng web ASP.NET 2.0 được điều hướng một phần bằng cách sử dụng các điều khiển DropDownList. Khi một trong số chúng được thay đổi, nó sẽ tạo ra một postback, sau đó được chuyển hướng đến một URL khác tùy thuộc vào những gì đã được chọn trong trình đơn thả xuống.ASP.NET postback từ danh sách thả xuống sai sau khi sử dụng trình duyệt Quay lại nút

Tôi đã nhận thấy hành vi lạ khi sử dụng nút Quay lại của trình duyệt sau khi sử dụng menu thả xuống. Thủ tục này là:

  1. Thực hiện lựa chọn trong một trong các menu thả xuống, gây ra postback và chuyển hướng. Tốt cho đến nay.
  2. Nhấp vào nút Quay lại của trình duyệt.
  3. Trong menu thả xuống điều hướng khác bên dưới hình ảnh được sử dụng trước (tất cả chúng đều có trong một div), hãy chọn. Trang này chuyển hướng đến cùng một URL như lần đầu tiên, không phải trang đích sẽ chuyển hướng đến dựa trên menu thả xuống khác này.

Tôi đã thử điều này trong cả Firefox 10 và IE9 và thấy điều tương tự. Tôi nhìn vào tab Net trong Firebug và thấy rằng trong POST cho bước 3, kiểm soát chính xác được tham chiếu. Nhưng khi tôi gỡ lỗi nó, trình xử lý sự kiện cho trình đơn thả xuống sai (cái được sử dụng trong bước 1) sẽ kích hoạt.

Mã này khá đơn giản và dễ hiểu. Ví dụ về đánh dấu:

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

Danh sách thả xuống thực sự không đơn giản là <asp:DropDownList ... /> phần tử; Tôi đang chèn optgroup các phần tử có cách tiếp cận tương tự như this.

Ví dụ về C#:

ddlTest.Click += new EventHandler(ddlTest_SelectedIndexChanged); 

Và trong ddlTest_SelectedIndexChanged:

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

gì đang xảy ra ở đây?

CẬP NHẬT 2/6/2012: Tôi đã khắc phục điều này bằng cách kiểm tra nội dung của Request["__EVENTTARGET"] trong trình xử lý sự kiện SelectedIndexChanged của tôi. Tôi vẫn tò mò tại sao nó lại xảy ra. Tại sao sự kiện đầu tiên lặp lại? Và tại sao nó chỉ xảy ra khi postback thứ hai xảy ra từ một điều khiển bên dưới cái đầu tiên?

+0

Bạn có thể thêm các thẻ từ trang cho menu thả xuống không? Sẽ giúp đỡ. –

+0

Thẻ cho menu thả xuống? Bạn có nghĩa là ID của họ trên trang? Hoặc đánh dấu của họ? Nó khá giống với đánh dấu tôi đã đăng trong câu hỏi. –

+0

Chỉ cần một gợi ý: Nav của bạn không thể hiện những gì tôi muốn gọi hành vi mong đợi ngay cả khi không sử dụng nút quay lại. Thông thường, nav được cho là được đồng bộ hóa với nội dung của bạn. Như vậy khi bạn nhấp vào tên trường, trường đó được chọn trong danh sách thả xuống của bạn. Trên thực tế, tôi càng nhìn nó càng cảm thấy * tắt *. Như thể bạn có thể loại bỏ toàn bộ điều hướng bên trái (chụp lại bất động sản đó) và cung cấp hai trình đơn thả xuống ở trên cùng: trường học và thể thao. Những người khác hoàn toàn phụ thuộc vào thông tin đó anyway ... $ 0,02 cho những gì giá trị của nó. – NotMe

Trả lời

3

Khi bạn bấm vào nút quay lại trang được truy cập lần cuối được hiển thị vì nó được lưu trên máy khách, không được gửi lại/yêu cầu lần nữa đến/từ máy chủ, bao gồm giá trị được đăng lần cuối như sau khi bạn chọn DropDownlist thứ hai ngay sau khi nhấn nút quay lại.

Phương pháp tải trên IE (đối với các trình duyệt khác xem: http: //dean.edwards.name/weblog/2005/09/busted/) của trang đầu tiên bị kích hoạt khi bạn nhấn nút quay lại thứ hai bằng cách này, chúng ta có thể cố gắng lưu hành động postback của khách trước khi chuyển hướng trang, chúng ta lưu nó trên một giá trị ẩn với JS, sau đó một khi người dùng quay trở lại các phương thức onload đánh giá nếu ẩn có giá trị và nếu vậy thì bạn thay đổi vị trí của trang cho chính nó để trang được yêu cầu một lần nữa và tất cả các giá trị đã đăng sẽ bị xóa:

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

bạn có thể sử dụng tính Response.Cache để giải quyết vấn đề này, như bạn đang cho phép bộ nhớ cache danh sách trong bộ nhớ của trình duyệt. từ MSDN SetAllowResponseInBrowserHistory

Khi HttpCacheability được thiết lập để nocache hoặc ServerAndNoCache các Expires tiêu đề HTTP là theo mặc định thiết lập để -1; điều này yêu cầu khách hàng không phải để lưu vào bộ nhớ cache trong thư mục Lịch sử, do đó khi bạn sử dụng các nút quay lại/chuyển tiếp , khách hàng yêu cầu một phiên bản mới của phản hồi mỗi lần. Bạn có thể ghi đè hành vi này bằng cách gọi phương thức SetAllowResponseInBrowserHistory với tham số cho phép đặt thành true.

trong phương pháp tải trang của bạn, bạn thêm dòng này.

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

để bất cứ khi nào bạn nhấn trở lại, t sẽ yêu cầu một phiên bản mới của ứng mỗi lần.

+0

Điều này trông giống như một sửa chữa tốt. Tôi đã cập nhật câu hỏi để làm rõ thông tin tôi đang tìm kiếm. –

+0

Tôi đã thử thêm hai dòng đầu tiên vào Page_Load của mình và sự cố vẫn xảy ra. –

3

Firefox - Thêm Mã Đằng sau:

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

Chrome - Thêm pageload javascript:

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

Một biến thể nhẹ trên câu trả lời từ @Ravi làm việc cho tôi ...

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

    .... 
}