ASP.NET - Невозможно перевести символ Юникода XXX по индексу YYY на указанную кодовую страницу

На веб-сайте ASP.NET 4 и im появляется следующая ошибка при попытке загрузить данные из базы данных в GridView.

Невозможно перевести символ Unicode\uD83D с индексом 49 на указанную кодовую страницу.

Я выяснил, что это происходит, когда строка данных содержит: Текст текстового текста 😊😊

Как я понимаю, этот текст не может быть переведен в действительный ответ utf-8.

  • Это действительно причина?

  • Есть ли способ очистить текст перед его загрузкой в ​​gridview, чтобы предотвратить такие ошибки?


UPDATE:

У меня есть некоторый прогресс Я обнаружил, что получаю эту ошибку только в том случае, когда использую метод Substring для строки. (Я использую подстроку, чтобы показать часть текста в виде предварительного просмотра для пользователя).

Например, в веб-форме ASP.NET я делаю это:

String txt = test 💔💔;

//txt string can also be created by 
String txt = char.ConvertFromUtf32(116) + char.ConvertFromUtf32(101) +char.ConvertFromUtf32(115) + char.ConvertFromUtf32(116) + char.ConvertFromUtf32(32) + char.ConvertFromUtf32(128148);

// this works ok txt is shown in the webform label.
Label1.Text = txt; 

//length is equal to 7.
Label2.Text = txt.Length.ToString();

//causes exception - Unable to translate Unicode character \uD83D at index 5 to specified code page.
Label3.Text = txt.Substring(0, 6);

Я знаю, что строка .NET основана на utf-16, которая поддерживает суррогатные пары.

Когда я использую функцию SubString, я случайно разбиваю суррогатную пару и вызывают исключение.   Я узнал, что могу использовать класс StringInfo:

var si = new System.Globalization.StringInfo(txt);
var l = si.LengthInTextElements; // length is equal to 6.
Label3.Text = si.SubstringByTextElements(0, 5); //no exception!

Другой альтернативой является просто удаление суррогатных пар:

Label3.Text = ValidateUtf8(txt).Substring(0, 3); //no exception!

    public static string ValidateUtf8(string txt)
            {
                StringBuilder sbOutput = new StringBuilder();
                char ch;

                for (int i = 0; i < body.Length; i++)
                {
                    ch = body[i];
                    if ((ch >= 0x0020 && ch <= 0xD7FF) ||
                            (ch >= 0xE000 && ch <= 0xFFFD) ||
                            ch == 0x0009 ||
                            ch == 0x000A ||
                            ch == 0x000D)
                    {
                        sbOutput.Append(ch);
                    }

                }
                return sbOutput.ToString();
            }

Действительно ли это проблема суррогатных пар?

Какие символы используют суррогатные пары? есть ли список?

Должен ли я поддерживать суррогатные пары? следует ли мне использовать StringInfo Class или просто удалить недействительные символы?

Спасибо!

Ответ 1

Вы можете попробовать сначала кодировать текст в UTF8 (в случае связанного с строкой события или что-то подобное). Следующий код кодирует текст в UTF8 и удаляет символы без кодирования.

private static readonly Encoding Utf8Encoder = Encoding.GetEncoding(
    "UTF-8",
    new EncoderReplacementFallback(string.Empty),
    new DecoderExceptionFallback()
);

var utf8Text = Utf8Encoder.GetString(Utf8Encoder.GetBytes(text));

Ответ 2

Символ U + 1F60A - символ эможи, введенный в Unicode 6.0. Его представление UTF-16 (SQL Server (вы не упомянули используемую базу данных) использует аналогичный UCS-2) - 0xD83D 0xDE0A с использованием суррогатных символов.

Поскольку Unicode 6.0 был выпущен в Oct 2010, я предполагаю, что либо SQL Server, либо (ASP).Net 4, либо преобразование между данными SQL Server и данными .Net не поддерживают кодовые точки emoji.

Ответ 3

Я только что узнал, что Маршрутизация запросов приложений, если она установлена ​​в IIS 7.5, заставит %2f обрабатываться по-разному, что вызовет проблемы.

Удаление ARR решило эту проблему для нас.