¿Qué causa esta "longitud no válida para una matriz de caracteres Base-64"

91

Tengo muy poco para continuar aquí. No puedo reproducir esto localmente, pero cuando los usuarios reciben el error, recibo una notificación automática de excepción por correo electrónico:

Invalid length for a Base-64 char array.

  at System.Convert.FromBase64String(String s)
  at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)
  at System.Web.UI.ObjectStateFormatter.System.Web.UI.IStateFormatter.Deserialize(String serializedState)
  at System.Web.UI.Util.DeserializeWithAssert(IStateFormatter formatter, String serializedState)
  at System.Web.UI.HiddenFieldPageStatePersister.Load()

Me inclino a pensar que hay un problema con los datos que se asignan a viewstate. Por ejemplo:

List<int> SelectedActionIDList = GetSelectedActionIDList();
ViewState["_SelectedActionIDList"] = SelectedActionIDList;

Es difícil adivinar la fuente del error sin poder reproducirlo localmente.

Si alguien ha tenido alguna experiencia con este error, realmente me gustaría saber qué averiguó.

Delgado
fuente

Respuestas:

36

He visto este error causado por la combinación de un estado de visualización de buen tamaño y dispositivos / firewalls agresivos de filtrado de contenido (especialmente cuando se trata de instituciones educativas K-12).

Lo solucionamos almacenando Viewstate en SQL Server. Antes de seguir esa ruta, recomendaría intentar limitar el uso de viewstate no almacenando nada grande en él y desactivándolo para todos los controles que no lo necesiten.

Referencias para almacenar ViewState en SQL Server:
MSDN - Descripción general de PageStatePersister
ASP Alliance - Método simple para almacenar viewstate en el proyecto de código de SQL Server
- Modelo de proveedor ViewState

Jimmie R. Houts
fuente
Copié el estado de vista de la página y lo pegué en Word. Tenía más de 86000 caracteres. Eso parece demasiado.
Slim
Vaya, me estoy encontrando con el problema ahora. He desactivado ViewState para todos los controles que puedo. Estoy usando un control de asistente con varias páginas y mucho contenido. ¿Algún consejo?
Mike Cole
@ Mike C., ¡este es un problema muy espantoso! Puede dividir el contenido de cada página del asistente en controles de usuario y cargar el contenido a pedido (¿a través de ajax?). Por supuesto, esta es solo una solución para esa página, si comienza a experimentar el problema de manera constante, es posible que desee considerar almacenar viewstate en su base de datos. Actualicé mi respuesta con referencias para almacenar viewstate en SQL Server.
Jimmie R. Houts
1
Otro problema con el que me he encontrado con más de 86000 caracteres de largo (en realidad puede estar cerca de 85K, creo, asumiendo caracteres de un solo byte) es que su aplicación .NET también puede comenzar a colocar cadenas de estado de vista en el montón de objetos grandes, lo que puede conducir a un montón fragmentación a lo largo del tiempo (y eventualmente OutOfMemoryException) si el grupo de aplicaciones no se recicla.
nada es necesario
Tengo el mismo problema, cómo resolver este problema, por favor, aclárelo.
Sajith
84

Después de que urlDecode procesa el texto, reemplaza todos los caracteres '+' con '' ... de ahí el error. Simplemente debe llamar a esta declaración para que sea compatible con la base 64 nuevamente:

        sEncryptedString = sEncryptedString.Replace(' ', '+');
Jalal El-Shaer
fuente
Buena cosa. Gracias. Estaba llamando a un servicio web ASP.NET desde una aplicación C ++ MFC y podría haberme ramificado en muchas direcciones tratando de resolver esto y después de haber pasado unas buenas horas en él. Me acaba de ahorrar un montón de tiempo.
nspire
3
Simplemente golpee este problema y, como dijiste, eran espacios, reemplazándolos por +arreglados. ¡Héroe!
mattytommo
¿Alguien puede dar orientación sobre dónde incluir este código? Estoy lidiando con este problema con frecuencia, pero a partir del fragmento de código, no puedo determinar dónde implementar la solución.
dst3p
@ dst3p Úselo en cualquier lugar del proceso de procesamiento donde se enfrente al error. Verifique el seguimiento de su pila y vea qué método está causando el error.
Jalal El-Shaer
21

Supongo que algo se codifica o descodifica con demasiada frecuencia, o que tiene texto con varias líneas.

Las cadenas Base64 deben tener una longitud de 4 caracteres; cada 4 caracteres representa 3 bytes de datos de entrada. De alguna manera, los datos de estado de vista que ASP.NET devuelve están dañados: la longitud no es un múltiplo de 4.

¿Registra el agente de usuario cuando esto ocurre? Me pregunto si es un navegador que se porta mal en alguna parte ... otra posibilidad es que haya un proxy haciendo cosas malas. Del mismo modo, intente registrar la longitud del contenido de la solicitud, para que pueda ver si solo ocurre para solicitudes grandes.

Jon Skeet
fuente
En mi caso, los navegadores son siempre Safari, ya sea en versión móvil o de escritorio
cockypup
12

Prueba esto:

public string EncodeBase64(string data)
{
    string s = data.Trim().Replace(" ", "+");
    if (s.Length % 4 > 0)
        s = s.PadRight(s.Length + 4 - s.Length % 4, '=');
    return Encoding.UTF8.GetString(Convert.FromBase64String(s));
}
Petr Voborník
fuente
Este método ayudó a resolver el problema. Aunque no utilicé codificación UTF8
Abhishek Shrivastava
10
int len = qs.Length % 4;
            if (len > 0) qs = qs.PadRight(qs.Length + (4 - len), '=');

¿Dónde qsestá cualquier cadena codificada en base64?

Bhuvana
fuente
8

Como han mencionado otros, esto puede deberse a que algunos firewalls y proxies impiden el acceso a páginas que contienen una gran cantidad de datos de ViewState.

ASP.NET 2.0 introdujo el mecanismo de fragmentación de ViewState que divide ViewState en partes manejables, lo que permite que ViewState pase a través del proxy / firewall sin problemas.

Para habilitar esta función, simplemente agregue la siguiente línea a su archivo web.config.

<pages maxPageStateFieldLength="4000">

Esto no debe usarse como una alternativa para reducir el tamaño de su ViewState, pero puede ser un respaldo efectivo contra el error "Longitud no válida para una matriz de caracteres Base-64" resultante de proxies agresivos y similares.

Taz rojo
fuente
¿Puede esto tener algún efecto secundario?
MonsterMMORPG
Ninguno que haya observado, más información en viewstate
Red Taz
Entonces, ¿cuál es tu longitud óptima? Lo configuré 1024
MonsterMMORPG
1

Esta no es una respuesta, lamentablemente. Después de encontrarme con el error intermitente durante algún tiempo y finalmente estar lo suficientemente molesto como para intentar solucionarlo, todavía tengo que encontrar una solución. Sin embargo, he determinado una receta para reproducir mi problema, lo que podría ayudar a otros.

En mi caso, es SOLAMENTE un problema de localhost, en mi máquina de desarrollo que también tiene la base de datos de la aplicación. Es una aplicación .NET 2.0 que estoy editando con VS2005. La máquina Win7 de 64 bits también tiene VS2008 y .NET 3.5 instalados.

Esto es lo que generará el error, a partir de una variedad de formas:

  1. Cargue una copia nueva del formulario.
  2. Ingrese algunos datos y / o devolución de datos con cualquiera de los controles del formulario. Siempre que no haya un retraso significativo, repita todo lo que quiera y no se producirán errores.
  3. Espere un poco (1 o 2 minutos tal vez, no más de 5) y pruebe con otra devolución.

Un minuto o dos de retraso "esperando localhost" y luego "La conexión fue restablecida" por el navegador, y global.asaxlos registros de captura de errores de la aplicación:

Application_Error event: Invalid length for a Base-64 char array.
Stack Trace:
     at System.Convert.FromBase64String(String s)
     at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString)
     at System.Web.UI.Util.DeserializeWithAssert(IStateFormatter formatter, String serializedState)
     at System.Web.UI.HiddenFieldPageStatePersister.Load()

En este caso, no es el TAMAÑO del estado de la vista, sino algo que tiene que ver con el almacenamiento en caché de la página y / o del estado de la vista lo que parece estar mordiendo. Configuración de <pages>parámetros enableEventValidation="false", y viewStateEncryption="Never"en el Web.configno cambió el comportamiento. Tampoco lo hizo establecer maxPageStateFieldLengthalgo modesto.

fortboise
fuente
1

Eche un vistazo a su HttpHandlers. He notado algunos errores extraños y completamente aleatorios en los últimos meses después de implementar una herramienta de compresión (RadCompression de Telerik). Estaba notando errores como:

  • System.Web.HttpException: no se pueden validar los datos.

  • System.Web.HttpException: el cliente se desconectó .---> System.Web.UI.ViewStateException: viewstate no válido.

y

  • System.FormatException: longitud no válida para una matriz de caracteres Base-64.

  • System.Web.HttpException: el cliente se desconectó. ---> System.Web.UI.ViewStateException: viewstate no válido.

Yo escribí sobre esto en mi blog.

Miguel
fuente
Tu blog está caído. ¿Tiene otro enlace o puede publicar la información relevante? thx
mga911
0

Esto se debe a un estado de vista enorme. En mi caso, tuve suerte ya que no estaba usando el estado de vista. Acabo de agregar enableviewstate="false"la etiqueta del formulario y el estado de la vista pasó de 35k a 100 caracteres

codificador
fuente
0

Durante la prueba inicial de Membership.ValidateUser con un SqlMembershipProvider, utilizo un algoritmo hash (SHA1) combinado con una sal y, si cambié la longitud de la sal a una longitud no divisible por cuatro, recibí este error.

No probé ninguna de las soluciones anteriores, pero si se modifica la sal, esto puede ayudar a alguien a identificarlo como la fuente de este error en particular.

Juan
fuente
0

Como dijo Jon Skeet, la cadena debe ser múltiplo de 4 bytes. Pero todavía recibía el error.

Al menos se eliminó en modo de depuración. Ponga un punto de interrupción y Convert.FromBase64String()luego siga el código. Milagrosamente, el error desapareció para mí :) Probablemente esté relacionado con los estados de Vista y otros problemas similares que otros han informado.

Hammad Khan
fuente
0

Además de la solución de @ jalchr que me ayudó, descubrí que al llamar ATL::Base64Encodedesde una aplicación C ++ para codificar el contenido que pasa a un servicio web ASP.NET, también necesita algo más. Además de

sEncryptedString = sEncryptedString.Replace(' ', '+'); 

de solución de @ jalchr, que también necesita asegurarse de que usted no usa laATL_BASE64_FLAG_NOPAD bandera en ATL::Base64Encode:

 BOOL bEncoded = Base64Encode(lpBuffer,
                    nBufferSizeInBytes,
                    strBase64Encoded.GetBufferSetLength(base64Length),
                    &base64Length,ATL_BASE64_FLAG_NOCRLF/*|ATL_BASE64_FLAG_NOPAD*/);
nspire
fuente