Что вызывает эту «Недопустимую длину для массива символов 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()

Я склонен думать, что есть проблема с данными, которые назначаются для viewstate. Например:

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

Трудно угадать источник ошибки, не имея возможности воспроизвести ошибку локально.

Если у кого-то был опыт работы с этой ошибкой, мне бы очень хотелось знать, что вы узнали.

Тонкий
источник

Ответы:

36

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

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

Ссылки по хранению ViewState в SQL Server:
MSDN - Обзор PageStatePersister
ASP Alliance - Простой метод сохранения состояния просмотра в проекте кода SQL Server
- Модель поставщика ViewState

Джимми Р. Хаутс
источник
Я скопировал вид страницы и вставил его в Word. Это было более 86000 символов. Это кажется слишком большим.
Slim
Ура, сейчас у меня проблема. Я отключил ViewState для всех возможных элементов управления. Я использую элемент управления Wizard с несколькими страницами и большим количеством контента. Любой совет?
Майк Коул,
@Mike C., это очень неприятная проблема! Вы можете разбить содержимое каждой страницы мастера на пользовательские элементы управления и загружать содержимое по запросу (через ajax?). Конечно, это решение только для этой одной страницы, если вы начнете постоянно сталкиваться с проблемой, вы можете подумать о сохранении состояния просмотра в своей базе данных. Я обновил свой ответ ссылками на сохранение состояния просмотра в SQL Server.
Джимми Р. Хаутс,
1
Другая проблема, с которой я столкнулся с длиной более 86000 символов (на самом деле, я думаю, может быть близка к 85K, я думаю, предполагая однобайтовые символы), заключается в том, что ваше приложение .NET может также начать помещать строки состояния просмотра в кучу больших объектов, что может привести к куче фрагментация со временем (и, в конечном итоге, OutOfMemoryException), если пул приложений не переработан.
ничего не нужно 09
У меня такая же проблема, как решить эту проблему, пожалуйста, поясните.
Саджит
84

После того, как urlDecode обработает текст, он заменяет все символы '+' на '' ... таким образом, возникает ошибка. Вы должны просто вызвать этот оператор, чтобы снова сделать его совместимым с базой 64:

        sEncryptedString = sEncryptedString.Replace(' ', '+');
Джалал Эль-Шаер
источник
Отличный материал. Спасибо. Я вызывал веб-службу ASP.NET из приложения C ++ MFC и мог разветвляться во многих направлениях, пытаясь решить эту проблему, и уже потратив на это несколько часов. Вы только что сэкономили мне кучу времени.
nspire 08
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
Абхишек Шривастава
11
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) и попробуйте еще один постбэк.

Задержка на минуту или две "ожидание локального хоста", затем "Соединение было сброшено" браузером, и 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что-то скромное.

Fortboise
источник
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 01
0

Это из-за огромного состояния просмотра. В моем случае мне повезло, так как я не использовал состояние просмотра. Я только что добавил enableviewstate="false"в тег формы, и состояние просмотра увеличилось с 35k до 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*/);
nspire
источник