Co powoduje ten „Nieprawidłowa długość tablicy znaków Base-64”

91

Mam tu bardzo mało do roboty. Nie mogę odtworzyć tego lokalnie, ale gdy użytkownicy otrzymają błąd, otrzymuję automatyczne powiadomienie e-mail o wyjątku:

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

Jestem skłonny myśleć, że jest problem z danymi, które są przypisywane do stanu widoku. Na przykład:

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

Trudno odgadnąć źródło błędu bez możliwości lokalnego odtworzenia błędu.

Jeśli ktoś miał jakieś doświadczenie z tym błędem, bardzo chciałbym wiedzieć, czego się dowiedziałeś.

Szczupły
źródło

Odpowiedzi:

36

Widziałem ten błąd spowodowany połączeniem dobrej wielkości stanu wyświetlania i agresywnych urządzeń filtrujących treści / zapór ogniowych (szczególnie w przypadku placówek edukacyjnych szkół podstawowych i ponadpodstawowych).

Obejrzeliśmy to, przechowując Viewstate w SQL Server. Przed pójściem tą trasą radziłbym spróbować ograniczyć użycie stanu widoku, nie zapisując w nim niczego dużego i wyłączając go dla wszystkich elementów sterujących, które go nie potrzebują.

Referencje dotyczące przechowywania ViewState w SQL Server:
MSDN - Omówienie PageStatePersister
ASP Alliance - Prosta metoda przechowywania stanu widoku w programie SQL Server
Code Project - ViewState Provider Model

Jimmie R. Houts
źródło
Skopiowałem stan strony i wkleiłem go do programu Word. Miał ponad 86 000 znaków. Wydaje się, że to za dużo.
Slim
Ups, mam teraz problem. Wyłączyłem ViewState dla wszystkich kontrolek, jakie mogłem. Używam formantu Kreatora z kilkoma stronami i dużą ilością treści. Jakakolwiek rada?
Mike Cole
@Mike C., to bardzo frustrujący problem! Możesz podzielić zawartość każdej strony kreatora na kontrolki użytkownika i załadować zawartość na żądanie (przez ajax?). Oczywiście jest to rozwiązanie tylko dla tej jednej strony, jeśli zaczniesz doświadczać problemu w sposób ciągły, możesz rozważyć zapisanie stanu widoku w bazie danych. Zaktualizowałem moją odpowiedź o odniesienia do przechowywania stanu widoku w SQL Server.
Jimmie R. Houts
1
Innym problemem, na który natknąłem się przy długości ponad 86000 znaków (myślę, że w rzeczywistości może to być blisko 85K, zakładając znaki jednobajtowe), jest to, że aplikacja .NET może również zacząć umieszczać ciągi stanu widoku na dużym stosie obiektów, co może prowadzić fragmentacja w czasie (i ostatecznie OutOfMemoryException), jeśli pula aplikacji nie zostanie odtworzona.
nic niepotrzebnego
Mam ten sam problem, jak rozwiązać ten problem, wyjaśnij go.
Sajith
84

Po przetworzeniu tekstu przez urlDecode zamienia wszystkie znaki „+” na „”… stąd błąd. Powinieneś po prostu wywołać tę instrukcję, aby ponownie była zgodna z bazą 64:

        sEncryptedString = sEncryptedString.Replace(' ', '+');
Jalal El-Shaer
źródło
Świetna sprawa. Dzięki. Wywoływałem usługę sieciową ASP.NET z aplikacji C ++ MFC i mogłem rozgałęzić się w wielu kierunkach, próbując rozwiązać ten problem i po spędzeniu nad tym dobrych kilku godzin. Właśnie zaoszczędziłeś mi trochę czasu.
nspire
3
Po prostu uderz w ten problem i jak powiedziałeś, były to spacje, zastępując je +naprawionymi. Bohater!
mattytommo
Czy ktoś może udzielić wskazówek, gdzie umieścić ten kod? Często mam do czynienia z tym problemem, ale na podstawie fragmentu kodu nie mogę określić, gdzie wdrożyć poprawkę.
dst3p
@ dst3p Użyj go wszędzie tam, gdzie w potoku przetwarzania napotkasz błąd. Sprawdź ślad stosu i zobacz, która metoda powoduje błąd.
Jalal El-Shaer
21

Domyślam się, że coś koduje lub dekoduje zbyt często - lub że masz tekst z wieloma wierszami.

Ciągi Base64 muszą być wielokrotnością 4 znaków - każde 4 znaki to 3 bajty danych wejściowych. W jakiś sposób dane o stanie widoku przesyłane z powrotem przez ASP.NET są uszkodzone - długość nie jest wielokrotnością 4.

Czy rejestrujesz agenta użytkownika, gdy to nastąpi? Zastanawiam się, czy to gdzieś źle zachowana przeglądarka ... Inną możliwością jest to, że proxy robi niegrzeczne rzeczy. Podobnie spróbuj zarejestrować długość treści żądania, aby zobaczyć, czy dzieje się to tylko w przypadku dużych żądań.

Jon Skeet
źródło
W moim przypadku przeglądarką jest zawsze Safari, wersja mobilna lub komputerowa
cockypup
12

Spróbuj tego:

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
źródło
Ta metoda pomogła rozwiązać problem. Chociaż nie używałem kodowania UTF8
Abhishek Shrivastava,
11
int len = qs.Length % 4;
            if (len > 0) qs = qs.PadRight(qs.Length + (4 - len), '=');

gdzie qsjest dowolny ciąg zakodowany algorytmem Base64

Bhuvana
źródło
8

Jak wspominali inni, może to być spowodowane przez niektóre zapory i serwery proxy, które uniemożliwiają dostęp do stron zawierających dużą ilość danych ViewState.

W ASP.NET 2.0 wprowadzono mechanizm ViewState Chunking, który dzieli ViewState na łatwe do zarządzania fragmenty, umożliwiając ViewState bezproblemowe przejście przez serwer proxy / zaporę.

Aby włączyć tę funkcję, po prostu dodaj następujący wiersz do pliku web.config.

<pages maxPageStateFieldLength="4000">

Nie należy tego używać jako alternatywy dla zmniejszania rozmiaru ViewState, ale może to być skuteczna ochrona przed błędem „Nieprawidłowa długość tablicy znaków Base-64” wynikającym z agresywnych serwerów proxy i tym podobnych.

Red Taz
źródło
czy może to mieć jakiś efekt uboczny?
MonsterMMORPG,
Żadnych, których nigdy nie zauważyłem, więcej informacji o stanie wyświetlania
Red Taz
więc jaka jest twoja optymalna długość? ustawiłem to na 1024
MonsterMMORPG
1

Niestety, to nie jest odpowiedź. Po pewnym czasie napotkania sporadycznego błędu i w końcu dostatecznie zdenerwowany, aby spróbować go naprawić, jeszcze nie znalazłem rozwiązania. Ustaliłem jednak przepis na odtworzenie mojego problemu, który może pomóc innym.

W moim przypadku jest to WYŁĄCZNIE problem z hostem lokalnym na moim komputerze deweloperskim, który ma również bazę danych aplikacji. To aplikacja .NET 2.0, którą edytuję za pomocą VS2005. Na 64-bitowym komputerze z systemem Windows 7 są również zainstalowane programy VS2008 i .NET 3.5.

Oto, co spowoduje błąd w różnych formach:

  1. Załaduj nową kopię formularza.
  2. Wprowadź dane i / lub ogłaszanie zwrotne za pomocą dowolnych kontrolek formularza. Dopóki nie ma znaczącego opóźnienia, powtórz wszystko, co chcesz, i nie wystąpią żadne błędy.
  3. Poczekaj chwilę (1 lub 2 minuty, nie więcej niż 5) i spróbuj ponownie.

Minuta lub dwie opóźnienie „oczekiwanie na localhost”, a następnie „Połączenie zostało zresetowane” przez przeglądarkę oraz global.asaxdzienniki pułapek błędów aplikacji:

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

W tym przypadku to nie ROZMIAR stanu widoku, ale coś, co ma związek z buforowaniem strony i / lub stanu widoku, wydaje mi się gryźć. Ustawianie <pages>parametrów enableEventValidation="false", a viewStateEncryption="Never"w Web.confignie zmienić zachowanie. Ani też nastawienie na maxPageStateFieldLengthcoś skromnego.

fortboise
źródło
1

Spójrz na swoje HttpHandlers. Zauważyłem kilka dziwnych i całkowicie przypadkowych błędów w ciągu ostatnich kilku miesięcy po wdrożeniu narzędzia do kompresji (RadCompression firmy Telerik). Zauważyłem takie błędy jak:

  • System.Web.HttpException: nie można zweryfikować danych.

  • System.Web.HttpException: klient rozłączył się. ---> System.Web.UI.ViewStateException: nieprawidłowy stan widoku.

i

  • System.FormatException: Nieprawidłowa długość tablicy znaków Base-64.

  • System.Web.HttpException: klient rozłączył się. ---> System.Web.UI.ViewStateException: Nieprawidłowy stan widoku.

I napisał o tym na moim blogu.

Michał
źródło
Twój blog nie działa. Czy masz inny link lub możesz zamieścić odpowiednie informacje? thx
mga911
0

Wynika to z ogromnego stanu widoku. W moim przypadku miałem szczęście, ponieważ nie korzystałem z tego stanu. Właśnie dodałem enableviewstate="false"tag w formularzu i stan widoku zmienił się z 35k na 100 znaków

koder
źródło
0

Podczas wstępnego testowania dla Membership.ValidateUser z SqlMembershipProvider używam algorytmu skrótu (SHA1) w połączeniu z solą, a jeśli zmieniłem długość soli na długość niepodzielną przez cztery, otrzymałem ten błąd.

Nie próbowałem żadnej z powyższych poprawek, ale jeśli sól jest zmieniana, może to pomóc komuś wskazać to jako źródło tego konkretnego błędu.

Jan
źródło
0

Jak powiedział Jon Skeet, ciąg musi być wielokrotnością 4 bajtów. Ale nadal otrzymywałem błąd.

Przynajmniej został usunięty w trybie debugowania. Umieść punkt przerwania, Convert.FromBase64String()a następnie przejdź przez kod. Cudem, błąd zniknął dla mnie :) Prawdopodobnie jest związany ze stanami View i podobnymi innymi problemami, jak zgłaszali inni.

Hammad Khan
źródło
0

Oprócz rozwiązania @ jalchr, które mi pomogło, odkryłem, że dzwoniąc ATL::Base64Encodez aplikacji C ++ w celu zakodowania treści przekazywanej do usługi sieciowej ASP.NET, potrzebujesz też czegoś innego. Oprócz

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

z rozwiązania @ jalchr, musisz również upewnić się, że nie używaszATL_BASE64_FLAG_NOPAD flagi na ATL::Base64Encode:

 BOOL bEncoded = Base64Encode(lpBuffer,
                    nBufferSizeInBytes,
                    strBase64Encoded.GetBufferSetLength(base64Length),
                    &base64Length,ATL_BASE64_FLAG_NOCRLF/*|ATL_BASE64_FLAG_NOPAD*/);
nspire
źródło