1

チェックボックスリストや検索結果を保持する2つのコンテナなど、いくつかのコントロールを備えたページがあります。

このサイトを永続化するように言われたので、ユーザーはサイトを閲覧しているときにどこからでも戻って、設定が復元されていることを確認できます(読み取り:チェックボックスがオンになっています。結果は引き続き利用可能です)

これまで、SavePageStateToPersistenceMediumとLoadPageStateFromPersitenceMediumをオーバーライドしようとしましたが、ページのボタンをクリックするとすぐに、常に黄色の死の画面が表示されます。

protected override void SavePageStateToPersistenceMedium(object viewState)
{
    string str = "VIEWSTATE_" + Request.UserHostAddress;
    Cache.Add(str, viewState, null, DateTime.Now.AddMinutes(Session.Timeout), TimeSpan.Zero, CacheItemPriority.Default, null);
    ClientScript.RegisterHiddenField("__VIEWSTATE_KEY", str);
    ClientScript.RegisterHiddenField("__VIEWSTATE", "");
}
protected override object LoadPageStateFromPersistenceMedium()
{
    string str = Request.Form["__VIEWSTATE_KEY"];
    if (!str.StartsWith("VIEWSTATE_"))
    {
        throw new Exception("Invalid viewstate key:" + str);
    }
    return Cache[str];
}

コードに何か問題がありますか?Page_LoadまたはPage_initでビューステートを取得するために何を呼び出す必要がありますか?

編集:これはsession["xyz"]を介してそれを解決するためのアプローチです

List<ListItem> selectItems = new List<ListItem>();
        foreach (ListItem item in CheckBoxListLevel.Items)
        {
            if (item.Selected)
                selectItems.Add(item);
        }

        Session.Add("SavedLevelItems", selectItems);

//そしてPage_Loadで

   if (Session["SavedLevelItems"] != null)
    {
        List<ListItem> SessionList = (List<ListItem>)Session["SavedLevelItems"];
        foreach (var item in SessionList)
        {
            if (item.Selected)
            {
                CheckBoxListLevel.Items.FindByText(item.Text).Selected = item.Selected;
            }
        }
    }

ただし、検索結果を表示してからGETを実行して最初のページに戻ると、保存されているすべてのアイテムが正しくレンダリングされません。

4

3 に答える 3

2

これによれば:

そのため、ユーザーはサイトを閲覧しているときにどこからでも戻ってきて、設定が復元されていることを確認できます(読み取り:チェックボックスがオンになっています。結果は引き続き利用可能です)

ビューステートは、同じページにいる間のみ機能します。ポストバック間でページの状態を記憶するために使用されます。別のページに移動すると、前のページのビューステートが失われます。この動作を変更することはできません。

あなたが探しているのはASP.Netプロファイルです

私は関連する質問に答えるだけです:

HTMLの状態をデータベースに保存します

于 2012-08-10T12:22:48.847 に答える
1

あなたのアプローチにはいくつかの困難があります。

差し迫った問題は__VIEWSTATE、メソッドに""隠しフィールドを手動で追加していることですSavePageStateToPersistenceMedium。これにより、ブラウザに送信されるhtmlページに2つの空の非表示フィールドがレンダリングされます。メソッドをオーバーライドしているため、ページはそのような空のフィールドを1つ自動的に送信します。

しかし、あなたのアプローチのより大きな問題は、LoadPageStateFromPersistenceMediumメソッドがポストバックを検出した場合にのみページによって呼び出されることです。

通常、ユーザーがサイト(またはその他のサイト)で何か他のことを行ってからページに戻った場合、ページは新しく読み込まれます(通常のGETなので、ポストバックではありません)。したがって、問題のページ用にキャッシュしたビューステートはロードされません。

問題を解決するには、ページのビューステート全体ではなく、ページのコントロールを再バインド/再初期化するのに十分な情報を保存する必要があると思います。次に、ページが読み込まれ、ポストバックではない場合は、保存された状態を取得してPage_Load、ページを再初期化できます。

状態を保存するには、次のようないくつかの可能な状態コンテナのいずれかを使用できます。

  • セッション
  • キャッシュ
  • SQLサーバーまたはその他のカスタムアウトプロセスストア
  • プロファイル(Jupaolが提案したように、これは少なくともSQLデータベースに格納されている「デフォルト」のAsp.Netプロバイダーを使用します)
于 2012-08-10T14:33:20.590 に答える
0

解決策は最終的には非常に単純でした。結果はいつでも変わる可能性があるため、ページ全体ではなく、一部のコントロールの状態のみが必要でした。

問題は、CheckBoxListsのデータソースがaspxファイルで定義されていることでした。これにより、Page_Load()を介してコントロールにアクセスしようとしたときに、アイテムがロードされませんでした。

そこで、データアクセスロジック全体を、ifステートメントでラップされたコードビハインドファイルに転送しました。適切なセッションオブジェクトが使用可能な場合、データソースはセッションオブジェクトです。それ以外の場合は、データベースから取得します。

 protected void fillEntrylevelList()
{
    using (OleDbConnection connection = new OleDbConnection(ConfigurationManager.ConnectionStrings["TestEnvironment"].ConnectionString))
    {
        string EntrylevelQuery = @"INSERT SQL STATEMENT HERE";
        OleDbCommand command = new OleDbCommand(EntrylevelQuery, connection);
        if (Session["SavedLevelItems"] != null)
            {
                CheckBoxListLevel.Items.Clear();
                List<ListItem> SessionList = (List<ListItem>)Session["SavedLevelItems"];
                foreach (var item in SessionList)
                {
                    try
                    {
                        CheckBoxListLevel.Items.Add(item);
                    }
                    catch { }

                }
            }
        else
        {
            connection.Open();
            CheckBoxListLevel.DataTextField = "bez_level";
            CheckBoxListLevel.DataValueField = "id_level";
            OleDbDataReader ListReader = command.ExecuteReader();
            CheckBoxListLevel.DataSource = ListReader;
            CheckBoxListLevel.DataBind();
            ListReader.Close(); ListReader.Dispose();
            GC.Collect();
        }
    }
}

敬具

于 2012-08-13T08:22:55.250 に答える