Как исправить отсутствующие DataKeys в Viewstate при использовании пользовательского PageStatePersister - PullRequest
0 голосов
/ 16 мая 2019

У нас есть веб-сайт, использующий Webforms. Мы хотим использовать пользовательский PageStatePersister, который сохраняет состояние просмотра в кэш redis (см. Код ниже). На уровне страницы мы переопределяем свойство PageStatePersister, чтобы использовать наш PageStatePersister. Пока что все работает нормально, но когда у нас есть элемент управления в другом элементе управления, мы сталкиваемся с несколькими проблемами.

   public class RedisPageStatePersister : PageStatePersister
    {
        const string ViewStateFieldName = "__VIEWSTATEKEY";
        const string ViewStateKeyPrefix = "ViewState_";

        public RedisPageStatePersister(Page page) : base(page)
        {
        }



        public override void Load()
        {
            var key = Page.UniqueID;


            // The cache key for this viewstate is stored in a hidden field, so grab it
            string viewStateKey = Page.Request.Form[ViewStateFieldName] as string;

            // Grab the viewstate data using the key to look it up
            if (viewStateKey != null)
            {
                var database = RedisConnectorHelper.Connection.GetDatabase(1);

                var viewstate = database.StringGet(viewStateKey);

                if (!viewstate.IsNull)
                {
                    Pair p = (Pair)StateFormatter.Deserialize(database.StringGet(viewStateKey));

                    ViewState = p.First;
                    ControlState = p.Second;
                }
            }
        }

        public override void Save()
        {
            string viewStateKey = Page.Request.Form[ViewStateFieldName] as string;

            if (viewStateKey == null)
            {
                viewStateKey = ViewStateKeyPrefix + Guid.NewGuid().ToString();
            }

            // Put viewstate data on writer
            var viewStateSerialized = StateFormatter.Serialize(new Pair(base.ViewState, base.ControlState));

            // Store the viewstate's key in a hidden field, so on postback we can grab it from the cache
            Page.ClientScript.RegisterHiddenField(ViewStateFieldName, viewStateKey);

            // Get the Redis database
            var database = RedisConnectorHelper.Connection.GetDatabase(1);

            // Save viewstate to the database
            database.StringSet(viewStateKey, viewStateSerialized, TimeSpan.FromMinutes(15));
        }
    }

Например:

  • При использовании ListViews. У нас есть ListView с DataKeys в другом ListView. При обратной передаче ключи данных не восстанавливаются для вложенного ListView
    <asp:ListView runat="server" ID="lvOuter" DataKeyNames="These,Keys,Work">
        <ItemTemplate>
            <asp:ListView runat="server" ID="lvInner" DataKeyNames="These,Keys,Dont,Work">
                <ItemTemplate></ItemTemplate>
            </asp:ListView>
        </ItemTemplate>
    </asp:ListView>
  • Мы используем динамическое создание TabPanel с GridView внутри. GridView внутри теряет свои значения datakeys при обратной передаче

Проблема, похоже, возникает только для DataKeys, например, использование HiddenField не является проблемой.

Я также пытался использовать SessionPageStatePersister, поскольку это встроенный персистер, но и здесь возникает проблема

Ниже фрагмента кода, где фиктивные данные связаны с представлением списка и его внутренним представлением списка. Ошибка возникает при нажатии на кнопку и попытке извлечь значения datakey из внутреннего списка. Свойство «DataKeys» является пустым списком, поэтому генерируется исключение IndexOutOfRangeException.

    public partial class InnerListViewTest : Page
    {
        public class Outer
        {
            public List<Inner> Inner { get; set; }

            public string Key1 { get; set; }

            public string Key2 { get; set; }
        }

        public class Inner
        {
            public string InnerKey1 { get; set; }
            public string InnerKey2 { get; set; }
        }

        protected void Page_Load(object sender, EventArgs e)
        {

            if (!IsPostBack)
            {
                var data = new List<Outer>();
                for (int i = 0; i < 5; i++)
                {
                    data.Add(new Outer()
                    {
                        Inner = new List<Inner>()
                        {
                            new Inner() {
                                InnerKey1 = "InnerData1_" + i,
                                InnerKey2 = "InnerData2_" + i
                            },
                            new Inner() {
                                InnerKey1 = "InnerData3_" + i,
                                InnerKey2 = "InnerData4_" + i
                            },
                            new Inner() {
                                InnerKey1 = "InnerData5_" + i,
                                InnerKey2 = "InnerData6_" + i
                            }
                        },
                        Key1 = "Data1_" + i,
                        Key2 = "Data2_" + i
                    });
                }

                lvOuter.DataSource = data;
                lvOuter.DataBind();
            }
        }

        protected void lvOuter_ItemDataBound(object sender, ListViewItemEventArgs e)
        {
            var outerData = e.Item.DataItem as Outer;

            var lvInner = e.Item.FindControl("lvInner") as ListView;
            lvInner.DataSource = outerData.Inner;
            lvInner.DataBind();
        }

        protected void Unnamed_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem outerItem in lvOuter.Items)
            {
                var lvInner = outerItem.FindControl("lvInner") as ListView;

                foreach (ListViewItem innerItem in lvInner.Items)
                {
                    var innerKey1 = lvInner.DataKeys[innerItem.DataItemIndex]["InnerKey1"];
                    var innerKey2 = lvInner.DataKeys[innerItem.DataItemIndex]["InnerKey2"];

                }
            }
        }
    }

Проблема, вероятно, связана со страницей, но я не могу понять, почему!

1 Ответ

1 голос
/ 16 мая 2019

Я уже нашел свой ответ!PageStatePersister нужно было включить с помощью PageAdapter вместо переопределения свойства страницы!

...