asp.net viewstate errors - “Base-64 char数组或字符串的长度无效。”和“输入不是有效的Base-64字符串”

时间:2014-02-03 15:46:37

标签: c# asp.net vb.net viewstate

我的.Net应用程序正在记录我跟踪到viewstate的一些错误。我已经阅读了相当多的内容,发现一些信息根本没有帮助我找到问题的根源。错误是:

  • Base-64字符数组或字符串的长度无效。
  • 输入不是有效的Base-64字符串,因为它包含非基本64个字符,两个以上的填充字符或填充字符中的非法字符。

这些错误很少发生,通常发生在同一小部分用户身上。通常,只是将用户重新定向到同一页面不会导致相同的错误

为了解决这些错误,我实施了两种不同的解决方案。在每个解决方案中,我尝试对空格进行字符串替换,并尝试通过附加“=”字符来确保视图状态字符串的长度合适。另外,在一次测试中我也压缩了视图状态。这些尝试的代码如下。

压缩的视图状态

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#解决方案也很受欢迎。

1 个答案:

答案 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} }。