Qu'est-ce qui cause cette "Longueur non valide pour un tableau de caractères Base-64"

91

J'ai très peu de choses à faire ici. Je ne peux pas reproduire cela localement, mais lorsque les utilisateurs obtiennent l'erreur, j'obtiens une notification d'exception par e-mail automatique:

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

J'ai tendance à penser qu'il y a un problème avec les données affectées à viewstate. Par exemple:

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

Il est difficile de deviner la source de l'erreur sans pouvoir reproduire l'erreur localement.

Si quelqu'un a eu une expérience avec cette erreur, j'aimerais vraiment savoir ce que vous avez découvert.

Svelte
la source

Réponses:

36

J'ai vu cette erreur causée par la combinaison d'un état de vue de bonne taille et de dispositifs de filtrage de contenu / pare-feu agressifs (en particulier lorsqu'il s'agit d'établissements d'enseignement K-12).

Nous avons contourné ce problème en stockant Viewstate dans SQL Server. Avant d'emprunter cette voie, je recommanderais d'essayer de limiter votre utilisation de viewstate en ne stockant rien de gros et en le désactivant pour toutes les commandes qui n'en ont pas besoin.

Références pour stocker ViewState dans SQL Server:
MSDN - Vue d'ensemble de PageStatePersister
ASP Alliance - Méthode simple pour stocker viewstate dans SQL Server
Code Project - Modèle de fournisseur ViewState

Jimmie R. Houts
la source
J'ai copié l'état de la page et l'ai collée dans Word. Il comptait plus de 86 000 caractères. Cela semble trop.
Slim
Yikes, je rencontre le problème maintenant. J'ai désactivé ViewState pour tous les contrôles que je peux éventuellement. J'utilise un contrôle Wizard avec plusieurs pages et beaucoup de contenu. Aucun conseil?
Mike Cole
@Mike C., c'est un problème très frustrant! Vous pouvez diviser le contenu de chaque page de l'assistant en contrôles utilisateur et charger le contenu à la demande (via ajax?). Bien sûr, il ne s'agit que d'une solution pour cette page, si vous commencez à rencontrer le problème de manière cohérente, vous pouvez envisager de stocker viewstate dans votre base de données. J'ai mis à jour ma réponse avec des références pour stocker viewstate dans SQL Server.
Jimmie R. Houts
1
Un autre problème que j'ai rencontré avec plus de 86000 caractères de long (en fait peut être proche de 85K je pense, en supposant des caractères à un octet) est que votre application .NET peut également commencer à mettre des chaînes viewstate sur le tas d'objets volumineux, ce qui peut conduire à un tas fragmentation au fil du temps (et éventuellement OutOfMemoryException) si le pool d'applications n'est pas recyclé.
rien n'est nécessaire
J'ai le même problème, comment résoudre ce problème, veuillez le clarifier.
Sajith
84

Une fois que urlDecode a traité le texte, il remplace tous les caractères '+' par '' ... donc l'erreur. Vous devez simplement appeler cette instruction pour la rendre à nouveau compatible avec la base 64:

        sEncryptedString = sEncryptedString.Replace(' ', '+');
Jalal El-Shaer
la source
Super truc. Merci. J'appelais un service Web ASP.NET à partir d'une application C ++ MFC et j'aurais pu bifurquer dans de nombreuses directions pour essayer de résoudre ce problème et après avoir déjà passé quelques bonnes heures dessus. Vous venez de me faire gagner du temps.
nspire
3
Frappez simplement ce problème et comme vous l'avez dit, il s'agissait d'espaces, en le remplaçant par un +corrigé. Héros!
mattytommo
Quelqu'un peut-il indiquer où inclure ce code? Je traite fréquemment ce problème, mais à partir de l'extrait de code, je ne peux pas déterminer où mettre en œuvre le correctif.
dst3p du
@ dst3p Utilisez-le partout dans le pipeline de traitement où vous rencontrez l'erreur. Vérifiez votre trace de pile et voyez quelle méthode est à l'origine de l'erreur.
Jalal El-Shaer
21

Je suppose que quelque chose est trop souvent encodé ou décodé - ou que vous avez du texte avec plusieurs lignes.

Les chaînes Base64 doivent être un multiple de 4 caractères - tous les 4 caractères représentent 3 octets de données d'entrée. D'une manière ou d'une autre, les données d'état d'affichage transmises par ASP.NET sont corrompues - la longueur n'est pas un multiple de 4.

Enregistrez-vous l'agent utilisateur lorsque cela se produit? Je me demande si c'est un navigateur qui se comporte mal quelque part ... une autre possibilité est qu'il y ait un proxy qui fasse des choses coquines. De même, essayez de consigner la longueur du contenu de la requête, afin de voir si cela ne se produit que pour les requêtes volumineuses.

Jon Skeet
la source
Dans mon cas, les navigateurs sont toujours Safari, soit en version mobile, soit en version bureau
cockypup
12

Essaye ça:

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
la source
Cette méthode a aidé à résoudre le problème. Bien que je n'ai pas utilisé l'encodage UTF8
Abhishek Shrivastava
10
int len = qs.Length % 4;
            if (len > 0) qs = qs.PadRight(qs.Length + (4 - len), '=');

qsest une chaîne encodée en base64

Bhuvana
la source
8

Comme d'autres l'ont mentionné, cela peut se produire lorsque certains pare-feu et proxys empêchent l'accès aux pages contenant une grande quantité de données ViewState.

ASP.NET 2.0 a introduit le mécanisme de segmentation ViewState qui divise le ViewState en morceaux gérables, permettant au ViewState de passer à travers le proxy / pare-feu sans problème.

Pour activer cette fonctionnalité, ajoutez simplement la ligne suivante à votre fichier web.config.

<pages maxPageStateFieldLength="4000">

Cela ne doit pas être utilisé comme une alternative à la réduction de la taille de votre ViewState, mais cela peut être un backstop efficace contre l'erreur "Longueur invalide pour un tableau de caractères Base-64" résultant de proxies agressifs et autres.

Taz rouge
la source
cela peut-il avoir un effet secondaire?
MonsterMMORPG
Aucun que j'ai jamais observé, plus d'informations sur viewstate
Red Taz
alors quelle est votre longueur optimale? Je l'ai mis 1024
MonsterMMORPG
1

Ce n'est malheureusement pas une réponse. Après avoir rencontré l'erreur intermittente pendant un certain temps et avoir finalement été assez ennuyé pour essayer de la réparer, je n'ai pas encore trouvé de solution. J'ai cependant déterminé une recette pour reproduire mon problème, ce qui pourrait aider les autres.

Dans mon cas, il s'agit UNIQUEMENT d'un problème d'hôte local, sur ma machine de développement qui a également la base de données de l'application. C'est une application .NET 2.0 que j'édite avec VS2005. La machine Win7 64 bits a également VS2008 et .NET 3.5 installés.

Voici ce qui générera l'erreur, sous diverses formes:

  1. Chargez une nouvelle copie du formulaire.
  2. Entrez des données et / ou publiez avec l'un des contrôles du formulaire. Tant qu'il n'y a pas de retard significatif, répétez tout ce que vous voulez et aucune erreur ne se produit.
  3. Attendez un peu (1 ou 2 minutes peut-être, pas plus de 5) et essayez une autre publication.

Un délai d'une minute ou deux "en attente de l'hôte local", puis "La connexion a été réinitialisée" par le navigateur, et global.asaxles journaux des interruptions d' erreurs de l'application:

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

Dans ce cas, ce n'est pas la TAILLE de l'état d'affichage, mais quelque chose à voir avec la mise en cache de la page et / ou de l'état d'affichage qui semble me mordre. Réglage des <pages>paramètres enableEventValidation="false", et viewStateEncryption="Never"dans le Web.confign'a pas changé le comportement. Il n'a pas non plus été mis maxPageStateFieldLengthà quelque chose de modeste.

fortboise
la source
1

Jetez un œil à vos HttpHandlers. J'ai remarqué des erreurs étranges et complètement aléatoires au cours des derniers mois après avoir implémenté un outil de compression (RadCompression de Telerik). Je remarquais des erreurs comme:

  • System.Web.HttpException: impossible de valider les données.

  • System.Web.HttpException: le client s'est déconnecté .---> System.Web.UI.ViewStateException: état d'affichage non valide.

et

  • System.FormatException: longueur non valide pour un tableau de caractères Base-64.

  • System.Web.HttpException: le client s'est déconnecté. ---> System.Web.UI.ViewStateException: état d'affichage non valide.

J'ai écrit à ce sujet sur mon blog.

Michael
la source
Votre blog est en panne. Avez-vous un autre lien ou pouvez-vous publier les informations pertinentes? thx
mga911
0

Ceci est dû à un état de vue énorme, dans mon cas, j'ai eu de la chance car je n'utilisais pas l'état de vue. Je viens d'ajouter enableviewstate="false"la balise de formulaire et l'état de la vue est passé de 35k à 100 caractères

coderman
la source
0

Lors du test initial pour Membership.ValidateUser avec un SqlMembershipProvider, j'utilise un algorithme de hachage (SHA1) combiné avec un sel, et, si j'ai changé la longueur du sel en une longueur non divisible par quatre, j'ai reçu cette erreur.

Je n'ai essayé aucune des corrections ci-dessus, mais si le sel est modifié, cela peut aider quelqu'un à identifier cela comme la source de cette erreur particulière.

John
la source
0

Comme l'a dit Jon Skeet, la chaîne doit être multiple de 4 octets. Mais j'obtenais toujours l'erreur.

Au moins, il a été supprimé en mode débogage. Mettez un point de rupture Convert.FromBase64String()puis parcourez le code. Miraculeusement, l'erreur a disparu pour moi :) Elle est probablement liée aux états de vue et à d'autres problèmes similaires, comme d'autres l'ont signalé.

Hammad Khan
la source
0

En plus de la solution de @ jalchr qui m'a aidé, j'ai trouvé que lorsque vous appelez ATL::Base64Encodedepuis une application C ++ pour encoder le contenu que vous passez à un service Web ASP.NET, vous avez également besoin d'autre chose. En plus de

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

à partir de la solution de @ jalchr, vous devez également vous assurer que vous n'utilisez pas l'ATL_BASE64_FLAG_NOPAD indicateur sur ATL::Base64Encode:

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