我的.Net应用程序正在记录我跟踪到viewstate的一些错误。我已经阅读了相当多的内容,发现一些信息根本没有帮助我找到问题的根源。错误是:
这些错误很少发生,通常发生在同一小部分用户身上。通常,只是将用户重新定向到同一页面不会导致相同的错误
为了解决这些错误,我实施了两种不同的解决方案。在每个解决方案中,我尝试对空格进行字符串替换,并尝试通过附加“=”字符来确保视图状态字符串的长度合适。另外,在一次测试中我也压缩了视图状态。这些尝试的代码如下。
压缩的视图状态
Public Class baseCompressor
Inherits System.Web.UI.Page
Protected Overrides Function LoadPageStateFromPersistenceMedium() As Object
Dim viewState As String = Request.Form("__VSTATE")
viewState = viewState.Replace(" ", "+")
Dim mod4 As Integer = viewState.Length Mod 4
If mod4 > 0 Then
viewState += New String("=", 4 - mod4)
End If
Dim bytes As Byte() = Convert.FromBase64String(viewState)
bytes = compressor.Decompress(bytes)
Dim formatter As New LosFormatter()
Return formatter.Deserialize(Convert.ToBase64String(bytes))
End Function
Protected Overrides Sub SavePageStateToPersistenceMedium(viewState As Object)
Dim formatter As New LosFormatter()
Dim writer As New StringWriter()
formatter.Serialize(writer, viewState)
Dim viewStateString As String = writer.ToString()
Dim bytes As Byte() = Convert.FromBase64String(viewStateString)
bytes = compressor.Compress(bytes)
ScriptManager.RegisterHiddenField(Me, "__VSTATE", Convert.ToBase64String(bytes))
End Sub
End Class
Public NotInheritable Class compressor
Private Sub New()
End Sub
Public Shared Function Compress(data As Byte()) As Byte()
Using output As New MemoryStream()
Using gzip As New GZipStream(output, CompressionMode.Compress, True)
gzip.Write(data, 0, data.Length)
gzip.Close()
Return output.ToArray()
End Using
End Using
End Function
Public Shared Function Decompress(data As Byte()) As Byte()
Using input As New MemoryStream()
input.Write(data, 0, data.Length)
input.Position = 0
Using gzip As New GZipStream(input, CompressionMode.Decompress, True)
Dim output As New MemoryStream()
Dim buff As Byte() = New Byte(4096) {}
Dim read As Integer = -1
read = gzip.Read(buff, 0, buff.Length)
While read > 0
output.Write(buff, 0, read)
read = gzip.Read(buff, 0, buff.Length)
End While
gzip.Close()
Return output.ToArray()
End Using
End Using
End Function
End Class
未压缩的Viewstate
Public Class baseNonCompressor
Inherits System.Web.UI.Page
Protected Overrides Sub SavePageStateToPersistenceMedium(viewState As Object)
Dim formatter As New LosFormatter()
Dim writer As New StringWriter()
formatter.Serialize(writer, viewState)
Dim viewStateString As String = writer.ToString()
Dim bytes As Byte() = Convert.FromBase64String(viewStateString)
ScriptManager.RegisterHiddenField(Me, "__VSTATE", Convert.ToBase64String(bytes))
End Sub
Protected Overrides Function LoadPageStateFromPersistenceMedium() As Object
Dim viewState As String = Request.Form("__VSTATE")
viewState = viewState.Replace(" ", "+")
Dim mod4 As Integer = viewState.Length Mod 4
If mod4 > 0 Then
viewState += New String("=", 4 - mod4)
End If
Dim bytes As Byte() = Convert.FromBase64String(viewState)
Dim formatter As New LosFormatter()
Return formatter.Deserialize(Convert.ToBase64String(bytes))
End Function
End Class
结果仍然给我留下了原来的两个错误以及一个新的错误:
Deserialize调用发生新错误。任何人都可以指出我的问题可能是什么?虽然我的代码是在VB中,但C#解决方案也很受欢迎。
答案 0 :(得分:1)
首先,您应该使用Base64
字符串,并确保它有效。
有许多在线工具。
这些可能是错的:
Dim mod4 As Integer = viewState.Length Mod 4
If mod4 > 0 Then
viewState += New String("=", 4 - mod4)
End If
从你的代码我感觉你已经知道为什么了。它只是想知道它是否真的在所有情况下都表现良好,例如,如果模数为0,则不应使用四个====
填充。
其次,考虑这是否经过GET
。 HTTP协议对状态行的最大长度有严格的限制。
换句话说:如果您将其设置为网址查询字符串中的参数,并且数据很大(接近1K),我强烈建议您选择POST
而不是{{1} }。