JavaScriptで再配置されたListBox要素により、ポストバック時にイベント検証エラーが発生する

StackOverflow https://stackoverflow.com/questions/212988

質問

2つのリストボックスと2つのリスト間でアイテムを交換できるいくつかのボタンで構成されるアイテムスワッパーコントロールを作成しました。スワッピングはjavascriptを使用して行われます。また、リスト内でアイテムを上下に移動します。基本的に、アイテムを右側のリストボックスに移動すると、要素のデータキー(GUID)が非表示フィールドに格納されます。ポストバックでは、フィールドからGUIDを読み取るだけです。すべてがうまく機能しますが、ポストバックでは、次の例外が発生します。

  

無効なポストバックまたはコールバック引数。イベント検証は、構成または<!> lt;%@ Page EnableEventValidation = <!> quot; true <!> quot;を使用して有効にします。 %<!> gt;ページ内。セキュリティのため、この機能は、ポストバックイベントまたはコールバックイベントへの引数が、それらを最初にレンダリングしたサーバーコントロールから発信されたことを検証します。データが有効で予想される場合、検証のためにポストバックまたはコールバックデータを登録するためにClientScriptManager.RegisterForEventValidationメソッドを使用します。

テストアプリケーションを準備しました。アーカイブをダウンロードしてプロジェクトを実行するだけです。 Webページで3つの項目を選択し、[すべて追加]を押してから、3番目の要素を1レベル上に移動し、<!> quot; Button <!> quot;を押します。エラーが表示されます。イベント検証をオフにすることは決して許容できません。誰も私を助けることができます、私は解決策を見つけることなく、すでに2日を過ごしました。

テストアプリケーション

役に立ちましたか?

解決 3

最初のオプションはかなりのオーバーヘッドをもたらします。リストボックスクラスから派生した独自のカスタムリストボックスコントロールを定義し、ロードポストバックデータのオーバーライドを実行しました。

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

ユーザーコントロールで通常のリストボックスの代わりにこれを使用すると、問題は解決しましたが、アプローチに関連するリスクはありますか?

他のヒント

問題は、リストの保存されたビューステートとポストバックで受信したデータが一致しないことです。イベント検証の問題は、このアプローチが原因で発生する可能性のある問題の1つにすぎない可能性があります。 Webフォームのアーキテクチャでは、この種の使用は許可されておらず、イベント検証の問題を回避できたとしても、このアプローチにはさらに多くの問題があります。いくつかの選択肢があります:

1)最も簡単なのは、javascriptを使用する代わりにサーバーでスワップロジックを実行することです。この方法では、ポストバック間でビューステートが保持され、サーバーへの複数のラウンドトリップの追加オーバーヘッドは問題になりません。

2)サーバーへの複数のラウンドトリップが問題である場合、それ自身のビューステートを処理するサーバーコントロールを記述します。もちろん、これは非常に魅力的なアプローチです。

3)中間的なアプローチは、2つの単純なhtmlリストを使用し(asp.netコントロールを使用せずにhtmlタグを記述するだけ)、クライアント側でjavascriptから非表示フィールドのIDのリストを維持することです。ポストバックでは、非表示フィールドを解析し、HTMLリストを無視してIDを抽出します。

それに対して深刻な引数がない場合、1を使用します。

いくつかの可能なオプション:

  • 可能であれば、2つのリストでViewStateを無効にします。 ViewStateがないと、サーバーは元の値が何であるかを認識できないため、エラーは発生しません。このアプローチでは、(ViewStateがないため)リストを再作成する必要があり、選択を手動で追跡する必要がある場合があります。または、OnInitフェーズ中にリストを作成する必要があります。

  • イベント検証をオフにします(可能な場合)

  • 両方のリストをサーバー側で完全に作成し、クライアント側スクリプト(javascript)を使用して、必要に応じて2つのリストからエントリを削除します。

偶然、これをすでに試しましたか?何らかの方法でリストをいじるたびにこれを行います。

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

リストで選択されたアイテムがレンダリングされたときにリストに存在しなかったため、不満を言っています。 PostBackではなくAJAXを介してPageMethodsを使用してデータをフォームに戻すことを検討してください。または、非入力コントロールを使用して、リスト要素を前後に移動する順序付けられていないリストのように、データを保持します。 GUIDは、必要に応じて取得できるリスト要素内の非表示のスパンに配置できます。

または、ListBoxの代わりにサーバー側のHtmlSelectを使用して、イベント検証の問題を回避できます。何よりも、コードビハインドの多くをそのまま残すことができる場合があります(つまり、リスト生成ロジックはListBoxと同じです)。

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

Renderイベントをオーバーライドして、可能なすべてのリストボックスアイテムを両方のリストボックスに登録できます。そのように、どのアイテムがどこに移動されても、検証ではそれらが期待されます。

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);
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top