Является ли IIS незаконной заменой символов? Если да, то как это остановить?
Контекст: ASP.NET MVC, работающий в IIS, с URL-адресом с кодировкой UTF-8%.
Используя стандартный шаблон проекта и тестовое действие в HomeController
, например:
public ActionResult Test(string id)
{
return Content(id, "text/plain");
}
Это отлично подходит для большинства% -кодированных маршрутов UTF-8, таких как:
http://mydevserver/Home/Test/%e4%ba%ac%e9%83%bd%e5%bc%81
с ожидаемым результатом 京都 弁
Однако используя маршрут:
http://mydevserver/Home/Test/%ee%93%bb
URL-адрес получен неверно.
Кроме того: %ee%93%bb
- это% -кодированная кодовая точка 0xE4FB; базовый-многоязычный самолет, частный сектор; но в конечном счете - действительная кодовая точка Юникода; вы можете проверить это вручную или через:
string value = ((char) 0xE4FB).ToString();
string encoded = HttpUtility.UrlEncode(value); // %ee%93%bb
Теперь, что будет дальше, зависит от веб-сервера; на сервере разработки Visual Studio (aka cassini) получен правильный id
- строка длиной одна, содержащая кодовую точку 0xE4FB.
Если, однако, я делаю это в IIS или IIS Express, я получаю другую id
, в частности "î"»"
, кодовые точки: 0xEE, 0x201C, 0xBB. Вы сразу узнаете первый и последний как начало и конец нашей кодированной в процентах строки... так что произошло в середине?
Ну:
Мне очень нравится, что при обработке моего URL-кода IIS выполнял какой-то котировочный перевод. Теперь, возможно, это может быть использовано в нескольких сценариях (я не знаю), но это, конечно, плохо, когда это происходит в середине блока с кодировкой% -encoded UTF-8.
Обратите внимание, что HttpContext.Current.Request.Raw
также показывает, что этот перевод произошел, поэтому это не похоже на ошибку MVC; обратите внимание также на комментарий Дарина, подчеркнув, что он работает по-разному в пути к части запроса URL-адреса.
Итак (двухпартер):
- В моем анализе отсутствует какая-то важная тонкость обработки unicode/url?
- Как я могу это исправить? (т.е. сделать так, чтобы я получил ожидаемый символ)
Ответы
Ответ 1
В конечном счете, чтобы обойти это, мне пришлось использовать request.ServerVariables["HTTP_URL"]
и некоторый ручной синтаксический анализ с кучей ошибок при обращении с ошибками (дополнительно компенсируя некоторые связанные сбои в Uri
). Не велико, но влияет только на незначительное меньшинство неудобных запросов.
Ответ 2
id = Encoding.UTF8.GetString(Encoding.Default.GetBytes(id));
Это даст вам исходный идентификатор.
IIS использует кодировку по умолчанию (ANSI) для символов пути. Строка, кодируемая вашим url, декодируется с использованием этого, и именно поэтому вы получаете странную вещь.
Чтобы получить исходный идентификатор, вы можете преобразовать его обратно в байты и получить строку с использованием кодировки utf8.
Смотрите Юникод и фильтры ISAPI
ISAPI Filter - это ANSI API - все значения, которые вы можете получить/установить с помощью API должен быть ANSI. Да, я знаю, что это шокирует; в конце концов, это 2006 год и все в настоящее время находится в Юникоде... но помните, что этот API возникла более десяти лет назад, когда почти ничего не было 32-битной, много меньше Unicode. Кроме того, помните, что протокол HTTP, который ISAPI непосредственно манипулирует в ANSI, а не в Юникоде.
EDIT: поскольку вы упомянули, что он работает с большинством других символов, поэтому я предполагаю, что IIS имеет какой-то механизм обнаружения кодирования, который в этом случае не работает. В качестве обходного пути, хотя вы можете префикс своего идентификатора с помощью этого char, а затем вы можете легко обнаружить, возникла ли проблема (если этот char отсутствует). Не очень идеальное решение, но оно будет работать. Затем вы можете написать свое собственное связующее устройство и класс-оболочку в ASP.NET MVC, чтобы сделать ваш код потребления более чистым.
Ответ 3
Однажды, сами URL-адреса не были в UTF-8. Они были на кодовой странице ANSI. Это облегчает тот факт, что они часто используются для выбора, ну, путей в файловой системе сервера. В древние времена IE имел возможность сказать, хотите ли вы отправлять URL UTF-8 или нет.
Возможно, захороненный в недрах конфигурации IIS, есть место, где можно указать кодировку URL и, возможно, нет.