Що спричиняє цю "Неправильну довжину масиву символів Base-64"


91

Мені тут дуже мало продовжувати. Я не можу відтворити це локально, але коли користувачі отримують помилку, я отримую автоматичне сповіщення про виключення електронної пошти:

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

Я схильний думати, що існує проблема з даними, які призначаються для перегляду стану. Наприклад:

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

Важко вгадати джерело помилки, не маючи можливості відтворити помилку локально.

Якщо хтось мав досвід цієї помилки, я б дуже хотів дізнатись, що ви з’ясували.

Відповіді:


36

Я бачив цю помилку, спричинену поєднанням великих розмірів огляду та надмірно агресивних пристроїв для фільтрації вмісту / брандмауерів (особливо коли мова йде про навчальні заклади K-12).

Ми обійшли це, зберігаючи Viewstate у SQL Server. Перш ніж йти цим маршрутом, я рекомендую спробувати обмежити використання viewstate, не зберігаючи в ньому нічого великого і вимкнувши його для всіх елементів керування, які в цьому не потребують.

Посилання для зберігання ViewState у SQL Server:
MSDN - Огляд PageStatePersister
ASP Alliance - Простий метод зберігання стану вигляду у проекті коду SQL Server
- Модель постачальника ViewState


Я скопіював veiwstate сторінки та вставив її у Word. Він містив понад 86000 символів. Це здається занадто.
Тонкий

Так, зараз я стикаюся з проблемою. Я вимкнув ViewState для всіх елементів керування, які я можу. Я використовую елемент керування Майстра з кількома сторінками та великою кількістю вмісту. Будь-яка порада?
Майк Коул

@Mike C., це дуже неприємна проблема! Ви можете розбити вміст кожної сторінки майстра на елементи керування користувача та завантажити вміст на вимогу (через ajax?). Звичайно, це рішення лише для цієї однієї сторінки, якщо ви почнете постійно відчувати проблему, можливо, ви захочете зберегти viewstate у вашій базі даних. Я оновив свою відповідь посиланнями для зберігання стану перегляду в SQL Server.
Джиммі Р. Хаутс

1
Ще одна проблема, з якою я зіткнувся з довжиною понад 86000 символів (насправді може бути близько 85K, я думаю, припускаючи однобайтові символи), це те, що ваша програма .NET також може почати розміщувати рядки viewstate у великій купі об'єктів, що може призвести до купи фрагментація з часом (і врешті-решт OutOfMemoryException), якщо пул програм не перероблений.
нічого непотрібного

У мене така ж проблема, як вирішити цю проблему, будь ласка, поясніть її.
Саджіт

84

Після того, як urlDecode обробляє текст, він замінює всі символи '+' на '' ... отже, помилка. Вам слід просто викликати це твердження, щоб зробити його базовим 64 знову сумісним:

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

Чудові речі. Дякую. Я дзвонив до веб-служби ASP.NET із програми C ++ MFC і міг розгалужитися в багатьох напрямках, намагаючись це вирішити, і вже витративши на це кілька годин. Ви щойно заощадили мені купу часу.
nspire

3
Просто натисніть цю проблему, і як ви вже сказали, це пробіли, замінивши на +виправлену. Герой!
mattytommo

Хтось може дати вказівки щодо того, куди включити цей код? Я часто маю справу з цією проблемою, але за допомогою фрагмента коду я не можу визначити, де застосувати виправлення.
dst3p

@ dst3p Використовуйте його скрізь, де в конвеєрі обробки ви стикаєтеся з помилкою. Перевірте трасування стека та перевірте, який метод спричиняє помилку.
Джалал Ель-Шаер

21

Я припускаю, що щось або кодується, або декодується занадто часто - або що у вас є текст із декількома рядками.

Рядки Base64 повинні бути кратні 4 символам - кожні 4 символи представляють 3 байти вхідних даних. Так чи інакше дані стану подання, що передаються ASP.NET, пошкоджені - довжина не кратна 4.

Ви реєструєте агент користувача, коли це відбувається? Цікаво, чи це десь погано вихований браузер ... інша можливість полягає в тому, що там є проксі, який робить неслухняні речі. Спробуйте також зареєструвати довжину вмісту запиту, щоб ви могли побачити, чи це відбувається лише для великих запитів.


У моєму випадку браузерами завжди є Safari, або мобільна, або настільна версія
cockypup

12

Спробуйте це:

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

Цей метод допоміг вирішити проблему. Хоча я не використовував кодування UTF8
Абхішек Шрівастава

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

де qs- будь-який рядок, закодований base64


8

Як згадували інші, це може бути спричинено тим, що деякі брандмауери та проксі-сервери перешкоджають доступу до сторінок, що містять велику кількість даних ViewState.

ASP.NET 2.0 представив механізм перебору ViewState, який розбиває ViewState на керовані фрагменти, дозволяючи ViewState проходити через проксі / брандмауер без проблем.

Щоб увімкнути цю функцію, просто додайте наступний рядок у файл web.config.

<pages maxPageStateFieldLength="4000">

Це не слід використовувати як альтернативу зменшенню розміру ViewState, але це може бути ефективним запобіжником проти помилки "Недійсна довжина масиву символів Base-64", що виникає внаслідок агресивних проксі-серверів тощо.


це може мати якийсь побічний ефект?
MonsterMMORPG

Жодного, що я коли-небудь спостерігав, більше інформації про viewstate
Red Taz

так яка ваша оптимальна довжина? я встановив це 1024
MonsterMMORPG

1

На жаль, це не відповідь. Натрапивши на переривчасту помилку протягом деякого часу і нарешті роздратувавшись, щоб спробувати її виправити, я ще не знайшов її виправлення. Однак я визначив рецепт відтворення своєї проблеми, який може допомогти іншим.

У моєму випадку це ВИСНОВО локальна проблема на моїй машині розробника, яка також має БД програми. Це програма .NET 2.0, яку я редагую за допомогою VS2005. На 64-розрядній машині Win7 також встановлені VS2008 та .NET 3.5.

Ось що призведе до помилки з різних форм:

  1. Завантажте нову копію форми.
  2. Введіть деякі дані та / або зворотну передачу за допомогою будь-якого елемента керування форми. Поки немає значної затримки, повторюйте все, що вам подобається, і помилок не виникає.
  3. Зачекайте трохи (можливо 1-2 хвилини, не більше 5) і спробуйте інший зворотний зв’язок.

Хвилина-дві затримки "очікування на localhost", а потім "З'єднання було скинуто" браузером, а також global.asaxжурнали перехоплення помилок програми:

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

У цьому випадку, здається, мене кусає не РОЗМІР стану перегляду, а щось спільне із кешуванням сторінок та / або представлення даних. Встановлюючи <pages>параметри enableEventValidation="false", і viewStateEncryption="Never"в Web.configне змінив поведінку. Так само як і не налаштувати maxPageStateFieldLengthщось на скромне.


1

Погляньте на свої HttpHandlers. Протягом останніх кількох місяців після того, як я застосував інструмент стиснення (RadCompression від Telerik), я помічав деякі дивні і абсолютно випадкові помилки. Я помітив такі помилки, як:

  • System.Web.HttpException: Не вдається перевірити дані.

  • System.Web.HttpException: Клієнт від'єднано .---> System.Web.UI.ViewStateException: Недійсне стан перегляду.

і

  • System.FormatException: недійсна довжина масиву символів Base-64.

  • System.Web.HttpException: Клієнт від’єднано. ---> System.Web.UI.ViewStateException: Недійсний стан перегляду.

Я писав про це у своєму блозі.


Ваш блог не працює. У вас є інше посилання або ви можете розмістити відповідну інформацію? thx
mga911


0

Це пов’язано з величезним станом перегляду. У моєму випадку мені пощастило, оскільки я не використовував viewstate. Я щойно додав enableviewstate="false"тег форми та стан перегляду зрісся з 35 тис. До 100 символів


0

Під час первинного тестування Membership.ValidateUser з SqlMembershipProvider я використовую алгоритм хешування (SHA1), поєднаний із сіллю, і, якщо я змінив довжину солі на довжину, що не ділиться на чотири, я отримав цю помилку.

Я не пробував жодного з наведених вище виправлень, але якщо сіль змінюється, це може допомогти комусь визначити це як джерело цієї конкретної помилки.


0

Як сказав Джон Скіт, рядок повинен бути кратним 4 байтам. Але я все ще отримував помилку.

Принаймні його видалено в режимі налагодження. Поставте точку розриву, Convert.FromBase64String()а потім перейдіть через код. Дивом, помилка для мене зникла :) Ймовірно, вона пов’язана із переглядом станів та подібними іншими проблемами, про які повідомляли інші.


0

На додаток до рішення @ jalchr, яке мені допомогло, я виявив, що під час виклику ATL::Base64Encodeіз програми c ++ для кодування вмісту, який ви передаєте веб-службі ASP.NET, вам потрібно ще щось. На додаток до

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

з рішення @ jalchr, вам також потрібно переконатися, що ви не використовуєтеATL_BASE64_FLAG_NOPAD прапор на ATL::Base64Encode:

 BOOL bEncoded = Base64Encode(lpBuffer,
                    nBufferSizeInBytes,
                    strBase64Encoded.GetBufferSetLength(base64Length),
                    &base64Length,ATL_BASE64_FLAG_NOCRLF/*|ATL_BASE64_FLAG_NOPAD*/);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.