Che cosa causa questa "Lunghezza non valida per un array di caratteri Base 64"


91

Ho molto poco su cui lavorare qui. Non riesco a riprodurlo localmente, ma quando gli utenti ottengono l'errore ricevo una notifica automatica di eccezione via e-mail:

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()

Sono propenso a pensare che ci sia un problema con i dati che vengono assegnati a viewstate. Per esempio:

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

È difficile indovinare l'origine dell'errore senza essere in grado di riprodurre l'errore localmente.

Se qualcuno ha avuto esperienza con questo errore, mi piacerebbe davvero sapere cosa hai scoperto.

Risposte:


36

Ho visto questo errore causato dalla combinazione di un viewstate di buone dimensioni e di dispositivi / firewall di filtraggio dei contenuti aggressivi (specialmente quando si tratta di istituzioni educative K-12).

Abbiamo risolto il problema archiviando Viewstate in SQL Server. Prima di intraprendere questa strada, consiglierei di provare a limitare l'uso di viewstate non memorizzando nulla di grande al suo interno e disattivandolo per tutti i controlli che non ne hanno bisogno.

Riferimenti per l'archiviazione di ViewState in SQL Server:
MSDN - Panoramica di PageStatePersister
ASP Alliance - Metodo semplice per archiviare viewstate in SQL Server
Code Project - ViewState Provider Model


Ho copiato il veiwstate della pagina e l'ho incollato in Word. Era lungo oltre 86000 caratteri. Sembra troppo.
Slim

Yikes, sto incontrando il problema ora. Ho disattivato ViewState per tutti i controlli che posso. Sto usando un controllo Wizard con diverse pagine e molti contenuti. Qualche consiglio?
Mike Cole

@ Mike C., questo è un problema davvero spaventoso! È possibile suddividere il contenuto di ogni pagina della procedura guidata in controlli utente e caricare il contenuto su richiesta (tramite ajax?). Naturalmente, questa è solo una soluzione per quella pagina, se inizi a riscontrare il problema in modo coerente, potresti prendere in considerazione la memorizzazione di viewstate nel tuo database. Ho aggiornato la mia risposta con i riferimenti per la memorizzazione di viewstate in SQL Server.
Jimmie R. Houts il

1
Un altro problema che ho riscontrato con oltre 86000 caratteri lunghi (in realtà potrebbe essere vicino a 85K penso, assumendo caratteri a byte singolo) è che la tua app .NET potrebbe anche iniziare a inserire stringhe di stato di visualizzazione sull'heap di oggetti di grandi dimensioni che può portare all'heap frammentazione nel tempo (ed eventualmente OutOfMemoryException) se il pool di app non viene riciclato.
niente è necessario il

Ho lo stesso problema, come risolvere questo problema per favore chiariscilo.
Sajith

84

Dopo che urlDecode elabora il testo, sostituisce tutti i caratteri "+" con "" ... quindi l'errore. Dovresti semplicemente chiamare questa istruzione per renderla nuovamente compatibile con la base 64:

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

Roba fantastica. Grazie. Stavo chiamando un servizio web ASP.NET da un'applicazione C ++ MFC e avrei potuto diramare in molte direzioni cercando di risolvere questo problema e dopo averci già trascorso alcune ore buone. Mi hai appena risparmiato un sacco di tempo.
nspire

3
Basta colpire questo problema e come hai detto era spazi, sostituendolo con +risolto. Eroe!
mattytommo

Qualcuno può fornire indicazioni su dove includere questo codice? Ho a che fare con questo problema frequentemente, ma dallo snippet di codice non riesco a determinare dove implementare la correzione.
dst3p

@ dst3p Usalo ovunque nella pipeline di elaborazione in cui devi affrontare l'errore. Controlla la tua traccia dello stack e vedi quale metodo sta causando l'errore.
Jalal El-Shaer

21

La mia ipotesi è che qualcosa stia codificando o decodificando troppo spesso o che tu abbia del testo con più righe.

Le stringhe Base64 devono essere un multiplo di 4 caratteri di lunghezza - ogni 4 caratteri rappresenta 3 byte di dati di input. In qualche modo, i dati sullo stato di visualizzazione restituiti da ASP.NET sono danneggiati: la lunghezza non è un multiplo di 4.

Registri l'agente utente quando ciò si verifica? Mi chiedo se da qualche parte si tratti di un browser mal funzionante ... un'altra possibilità è che ci sia un proxy che fa cose cattive. Allo stesso modo, prova a registrare la lunghezza del contenuto della richiesta, in modo da poter vedere se accade solo per richieste di grandi dimensioni.


Nel mio caso il browser è sempre Safari, sia in versione mobile che desktop
cockypup

12

Prova questo:

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));
}

Questo metodo ha aiutato a risolvere il problema. Anche se non ho utilizzato la codifica UTF8
Abhishek Shrivastava

10
int len = qs.Length % 4;
            if (len > 0) qs = qs.PadRight(qs.Length + (4 - len), '=');

dove qsè qualsiasi stringa codificata in base64


8

Come altri hanno già detto, ciò può essere causato quando alcuni firewall e proxy impediscono l'accesso a pagine contenenti una grande quantità di dati ViewState.

ASP.NET 2.0 ha introdotto il meccanismo ViewState Chunking che suddivide ViewState in blocchi gestibili, consentendo a ViewState di passare attraverso il proxy / firewall senza problemi.

Per abilitare questa funzione è sufficiente aggiungere la seguente riga al file web.config.

<pages maxPageStateFieldLength="4000">

Questo non dovrebbe essere usato come alternativa alla riduzione delle dimensioni di ViewState, ma può essere un backstop efficace contro l'errore "Lunghezza non valida per un array di caratteri Base-64" risultante da proxy aggressivi e simili.


questo può avere qualche effetto collaterale?
MonsterMMORPG

Nessuno che io abbia mai osservato, maggiori informazioni su viewstate
Red Taz

allora qual è la tua lunghezza ottimale? l'ho impostato 1024
MonsterMMORPG

1

Questa non è una risposta, purtroppo. Dopo essermi imbattuto nell'errore intermittente per un po 'di tempo e finalmente essere stato abbastanza infastidito da provare a risolverlo, devo ancora trovare una soluzione. Tuttavia, ho stabilito una ricetta per riprodurre il mio problema, che potrebbe aiutare gli altri.

Nel mio caso è SOLAMENTE un problema di localhost, sulla mia macchina di sviluppo che ha anche il DB dell'app. È un'app .NET 2.0 che sto modificando con VS2005. La macchina Win7 a 64 bit ha anche VS2008 e .NET 3.5 installati.

Ecco cosa genererà l'errore, da una varietà di forme:

  1. Carica una nuova copia del modulo.
  2. Inserisci alcuni dati e / o postback con uno dei controlli del modulo. Finché non ci sono ritardi significativi, ripeti tutto quello che vuoi e non si verificano errori.
  3. Aspetta un po '(1 o 2 minuti forse, non più di 5) e prova un altro postback.

Uno o due minuti di ritardo "in attesa di localhost" e poi "Connessione ripristinata" dal browser, e global.asaxi registri delle trap degli errori dell'applicazione di:

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()

In questo caso, non è la DIMENSIONE del viewstate, ma qualcosa che ha a che fare con la cache di pagina e / o viewstate che sembra mordermi. L'impostazione dei <pages>parametri enableEventValidation="false"e viewStateEncryption="Never"in Web.confignon ha modificato il comportamento. Nemmeno l'impostazione maxPageStateFieldLengthdi qualcosa di modesto.


1

Dai un'occhiata al tuo HttpHandlers. Ho notato alcuni errori strani e completamente casuali negli ultimi mesi dopo aver implementato uno strumento di compressione (RadCompression di Telerik). Notavo errori come:

  • System.Web.HttpException: impossibile convalidare i dati.

  • System.Web.HttpException: il client si è disconnesso .---> System.Web.UI.ViewStateException: viewstate non valido.

e

  • System.FormatException: lunghezza non valida per una matrice di caratteri Base-64.

  • System.Web.HttpException: il client si è disconnesso. ---> System.Web.UI.ViewStateException: viewstate non valido.

Ne ho scritto sul mio blog.


Il tuo blog non funziona. Hai un altro link o puoi pubblicare le informazioni pertinenti? thx
mga911


0

Ciò è dovuto a un enorme stato di visualizzazione, nel mio caso sono stato fortunato poiché non utilizzavo il viewstate. Ho appena aggiunto enableviewstate="false"il tag del modulo e lo stato di visualizzazione è passato da 35k a 100 caratteri


0

Durante i test iniziali per Membership.ValidateUser con un SqlMembershipProvider, utilizzo un algoritmo hash (SHA1) combinato con un salt e, se ho modificato la lunghezza del salt in una lunghezza non divisibile per quattro, ho ricevuto questo errore.

Non ho provato nessuna delle correzioni sopra, ma se il sale viene alterato, questo potrebbe aiutare qualcuno a individuarlo come la fonte di questo particolare errore.


0

Come ha detto Jon Skeet, la stringa deve essere multipla di 4 byte. Ma stavo ancora ricevendo l'errore.

Almeno è stato rimosso in modalità di debug. Metti un punto di interruzione, Convert.FromBase64String()quindi segui il codice. Miracolosamente, l'errore è scomparso per me :) Probabilmente è correlato agli stati di visualizzazione e ad altri problemi simili come altri hanno segnalato.


0

Oltre alla soluzione di @ jalchr che mi ha aiutato, ho scoperto che quando si chiama ATL::Base64Encodeda un'applicazione c ++ per codificare il contenuto che si passa a un servizio Web ASP.NET, è necessario anche qualcos'altro. Inoltre

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

dalla soluzione di @ jalchr, devi anche assicurarti di non utilizzare ilATL_BASE64_FLAG_NOPAD flag su ATL::Base64Encode:

 BOOL bEncoded = Base64Encode(lpBuffer,
                    nBufferSizeInBytes,
                    strBase64Encoded.GetBufferSetLength(base64Length),
                    &base64Length,ATL_BASE64_FLAG_NOCRLF/*|ATL_BASE64_FLAG_NOPAD*/);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.