Хранение состояния страниц на сервере
Для того, чтобы увидеть ViewState своей странички, достаточно в Page_load записать:
00001: If Not (Me.Request.Form("__VIEWSTATE")) Is Nothing Then 00002: Session("ViewState") = Me.Request.Form("__VIEWSTATE") 00003: End If
А в Prerender:
00001: If Not (Session("ViewState") Is Nothing) Then 00002: Dim X() As Byte = Convert.FromBase64String(Session("ViewState")) 00003: Panel3.Controls.Add(New LiteralControl(System.Text.Encoding.ASCII.GetString(X))) 00004: Panel3.Controls.Add(New LiteralControl("<BR><BR><BR>")) 00005: Dim Z As New LosFormatter 00006: Dim A As Object = Z.Deserialize(Session("ViewState").ToString.Replace("\n", "").Replace("\r", "")) 00007: End If
Тогда на страничке мы увидет что-то вроде:
? -1512249231dfddddd PostBackUrl~/Link/Page1_LoadStart.aspxdd NavigateUrl~/Link/Page1_LoadStart.aspxdd~/Link/Page1_Filter.aspxdd~/Link/Page1_Filter.aspxdd~/Link/Page1_Filter.aspxdd~/Link/Page1_Filter.aspxdd _!DataBoundgd C????????1gIPOD2g.???????????????????? ?????? ??????????????????3g=???????????????????? ?? ?????????????????? ??????????????????4g????????????????????5g??????????, ??????????6g!???????????????????????? ????????7g????????8g????????????????9g??????????????????????????10g????????????????????11g ????????????12g????????????????13g
C помощью класса Pair и Triplets можно полностью разобрать ViewState в полную древовидную структуру, но у меня это не получается, тк LosFormatter.Deserialize упрямо пишет "The serialized data is invalid.
Для облегчения участи клиентов, которые забрели на ваш ASP2-сайт, ViewState рекомендуется хранить на сервере (в базе или кеше). Делается это вроде бы вот таким простейшим способом:
00001: Protected Overrides Sub SavePageStateToPersistenceMedium(ByVal state As Object) 00002: 'MyBase.SavePageStateToPersistenceMedium(state) 00003: Session("ViewState#") = state 00004: End Sub 00005: 00006: Protected Overrides Function LoadPageStateFromPersistenceMedium() As Object 00007: 'Return MyBase.LoadPageStateFromPersistenceMedium() 00008: Return Session("ViewState#") 00009: End Function
Однако так при пейжинге таблы получается ошибка. Цепляться за SessionID также нельзя, так как, как это не неожиданно, он может меняться (пока к нему не было обращений). Наиболее надежным вариантом на практике оказывается создание собственного ключа и сохранение его на страничке:
00001: Protected Overrides Sub SavePageStateToPersistenceMedium(ByVal state As Object) 00002: 'создали уникальный ключ и его вписали вместо самого ViewState, а сам ViewState оставили у себя в кеше 00003: Dim Key As String = "Page1#" & Request.UserHostAddress & "#" & DateTime.Now.Ticks.ToString() 00004: Cache.Add(Key, State, Nothing, DateTime.Now.AddMinutes(Session.Timeout), TimeSpan.Zero, CacheItemPriority.NotRemovable, Nothing) 00005: ClientScript.RegisterHiddenField("__VIEWSTATE_KEY", Key) 00006: End Sub 00007: 00008: Protected Overrides Function LoadPageStateFromPersistenceMedium() As Object 00009: Dim Key As String = Request.Form("__VIEWSTATE_KEY") 00010: If Key.StartsWith("Page1#") Then 00011: If Cache.Get(Key) Is Nothing Then 00012: Throw New Exception("Кеш утерян: " + Key) 00013: Else 00014: Return Cache.Get(Key) 00015: End If 00016: Else 00017: Throw New Exception("ViewState испорчен: " + Key) 00018: End If 00019: End Function
С таким же ключом это можно ложить и в базу и триггером удалять устаревшие записи. Что конечно медленнее, зато гораздо надежнее. Вообще-то кеш в ASP2 работает плохо, записи теряет только так и при недостатке памяти он потеряется все равно. (При работе с кешем, учтите, что отладчик кеш просматривать не умеет, помочь может это).
|