2008-10-17 24 views
5

Tôi đã tạo một điều khiển mục swapper bao gồm hai hộp danh sách và một số nút cho phép tôi trao đổi các mục giữa hai danh sách. Việc trao đổi được thực hiện bằng cách sử dụng javascript. Tôi cũng di chuyển các mục lên xuống trong danh sách. Về cơ bản khi tôi di chuyển các mục vào hộp danh sách bên phải tôi lưu trữ các datakeys của các yếu tố (GUIDs) trong một lĩnh vực ẩn. Ngày postback tôi chỉ cần đọc GUIDs từ lĩnh vực này. Mọi thứ đều hoạt động tốt nhưng khi đăng lại, tôi nhận được ngoại lệ sau:Các phần tử ListBox được sắp xếp lại với JavaScript gây ra lỗi xác thực sự kiện trên postback

Đối số hoặc trả lại cuộc gọi không hợp lệ. Xác thực sự kiện được bật bằng cấu hình hoặc <% @ Page EnableEventValidation = "true"%> trong một trang. Vì mục đích bảo mật, tính năng này xác minh rằng các đối số cho các sự kiện postback hoặc gọi lại bắt nguồn từ điều khiển máy chủ ban đầu được hiển thị. Nếu dữ liệu hợp lệ và được mong đợi, hãy sử dụng phương thức ClientScriptManager.RegisterForEventValidation để đăng ký dữ liệu đăng lại hoặc gọi lại để xác thực.

Tôi đã chuẩn bị một ứng dụng thử nghiệm. Tất cả những gì bạn phải làm là tải xuống bản lưu trữ và chạy dự án. Trên trang web chọn 3 mục, nhấn Thêm tất cả, sau đó di chuyển phần tử thứ ba lên một cấp và sau đó nhấn "Nút". Lỗi sẽ hiển thị. Tắt xác thực sự kiện là không có nghĩa là chấp nhận được. Bất cứ ai có thể giúp tôi, tôi đã dành hai ngày rồi mà không tìm ra giải pháp.

TEST APPLICATION

+0

FYI: Tôi đã tải xuống ứng dụng của bạn và không bao giờ gặp lỗi này - tuy nhiên, tôi gặp lỗi về col1 không phải là một phần của bảng dữ liệu hoặc một cái gì đó tương tự (không nhìn vào nó ngay bây giờ). Bạn có thể muốn kiểm tra để chắc chắn rằng ví dụ của bạn gây ra lỗi này, bởi vì nó không cho tôi. –

+0

Ngoài ra, việc 'di chuyển' qua lại không hoạt động ở tất cả trong Firefox, bạn có thể muốn đề cập đến hoặc sửa chữa nó. –

+0

Lỗi với col1 được gây ra do destinationDT.Columns.Add ("colUID", typeof (Guid)); và destinationDT.Columns.Add ("col1", typeof (string)); chỉ được gọi nếu không đăng bài trở lại nhưng được yêu cầu khi nút được nhấp. – Aleris

Trả lời

0

Tùy chọn đầu tiên sẽ mang lại chi phí đáng kể. Tôi đã xác định riêng điều khiển tùy chỉnh listbox của tôi bắt nguồn từ lớp ListBox và thực hiện một ghi đè dữ liệu loadpostback:

public class CustomListBox : ListBox 
{ 
    protected override bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection) 
    { 
     return true; 
    } 
} 

Sử dụng này thay vì ListBox thường xuyên trong kiểm soát của tôi sử dụng giải quyết vấn đề, tuy nhiên là có bất kỳ rủi ro liên quan với cách tiếp cận của tôi?

+0

Bạn có thể muốn trả về false nếu bạn thực hiện điều này - trả về true sẽ khiến SelectedIndexChanged luôn kích hoạt, nhưng vì bạn đã ghi đè bit mà điền SelectedIndex từ dữ liệu bài đăng, nó sẽ không bao giờ thực sự thay đổi. – stevemegson

0

Nó phàn nàn vì mục đã chọn trong một danh sách đã không có mặt trong danh sách khi nó được trả lại. Cân nhắc sử dụng PageMethods qua AJAX để đưa dữ liệu của bạn trở lại biểu mẫu thay vì PostBack. Hoặc sử dụng một điều khiển không đầu vào để giữ dữ liệu - như danh sách không có thứ tự mà bạn di chuyển các phần tử danh sách qua lại giữa. Bạn có thể đặt GUID trong các khoảng trống ẩn bên trong phần tử danh sách nơi bạn có thể nhận được chúng nếu cần.

+0

Tuy nhiên, nếu tôi chỉ đơn giản di chuyển các phần tử từ danh sách bên trái sang bên phải và sau đó postback mà không thay đổi thứ tự của chúng (lên hoặc xuống) thì mọi thứ đều ổn. Trong trường hợp này, không phải là hai danh sách khác nhau trên postback so với khi trang đã được viết? – kjv

+0

Chính xác hơn, nó phàn nàn vì giá trị đã chọn trong danh sách không có trong danh sách khi trang được viết. Thêm mục là tốt, nhưng sắp xếp lại chúng để lại một mục được chọn và do đó gây ra vấn đề. – stevemegson

+0

Mô tả sự cố. – tvanfosson

3

Sự cố là trạng thái chế độ xem đã lưu của danh sách và dữ liệu nhận được khi đăng lại không khớp. Sự cố xác thực sự kiện rất có thể chỉ là một trong những vấn đề có thể xuất hiện do cách tiếp cận này. Kiến trúc của biểu mẫu web không cho phép sử dụng loại này và, rất có thể, sẽ có nhiều vấn đề hơn với phương pháp này, ngay cả khi bạn thành công để tránh sự cố xác thực sự kiện. Bạn có một số lựa chọn thay thế:

1) Cách đơn giản nhất là thực hiện logic hoán đổi trên máy chủ thay vì sử dụng javascript. Bằng cách này, trạng thái xem sẽ được giữ nguyên giữa các lần đăng lại và chi phí bổ sung của nhiều chuyến đi khứ hồi tới máy chủ có thể không phải là vấn đề.

2) Nếu các chuyến đi nhiều vòng tới máy chủ là một vấn đề, hãy viết điều khiển máy chủ xử lý trạng thái chế độ xem của chính nó. Tất nhiên đây là một cách tiếp cận hấp dẫn.

3) Phương pháp tiếp cận mặt đất trung bình có thể sử dụng hai danh sách html đơn giản (chỉ cần viết thẻ html mà không sử dụng điều khiển asp.net) và duy trì ở phía máy khách từ javascript danh sách id trong trường ẩn. Khi đăng lại, chỉ phân tích cú pháp trường ẩn và trích xuất các id bỏ qua danh sách html.

Tôi sẽ đi với 1 nếu không có đối số SERIOUS chống lại nó.

1

Một vài tùy chọn có thể:

  • Nếu có thể, vô hiệu hóa ViewState trên hai danh sách. Nếu không có ViewState, máy chủ sẽ không biết giá trị ban đầu là gì và do đó sẽ không bị lỗi. Với cách tiếp cận này, bạn sẽ cần phải repopulate các danh sách (do thiếu ViewState) và có thể cần phải theo dõi các lựa chọn bằng tay - hoặc sẽ cần phải cư trú trong danh sách trong giai đoạn OnInit.

  • Tắt xác nhận sự kiện (nếu bạn có thể)

  • dụng nhất cả hai danh sách đầy đủ ở phía máy chủ và sử dụng kịch bản phía máy khách (javascript) để loại bỏ đi từ hai danh sách theo yêu cầu.

0

Cơ hội, bạn đã thử điều này chưa? Làm điều này bất cứ khi nào bạn muck với danh sách trong bất kỳ cách nào.

document.getElementById("listbox").selectedIndex = -1; 
0

Ngoài ra, bạn có thể sử dụng phía máy chủ HtmlChọn vị trí của ListBox để giải quyết vấn đề xác thực sự kiện. Hay nhất của tất cả, bạn có thể để lại nhiều mã của bạn-đằng sau còn nguyên vẹn (ví dụ: danh sách logic dân số là giống như ListBox).

<select runat="server" id="myList" multiple="true" /> 
0

Bạn có thể ghi đè sự kiện Render để đăng ký tất cả các mục hộp danh sách có thể có cả hai hộp danh sách. Bằng cách đó không có vấn đề gì các mục được di chuyển ở đâu, xác nhận là mong đợi họ.

protected override void Render(HtmlTextWriter writer) 
{ 
    foreach (DictionaryEntry entry in ColumnConfig) {   
    Page.ClientScript.RegisterForEventValidation(lstbxColumnsToExport.UniqueID,(string)entry.Key); 
    Page.ClientScript.RegisterForEventValidation(lstbxNonExportColumns.UniqueID,(string)entry.Key); 
    } 
    base.Render(writer); 
} 
Các vấn đề liên quan