Создание приложений .NET с поддержкой IDN сайтов

    • .NET
    • C#
    • web
    • Sample
    • IDN
    • Punycode
    • Internationalized domain name
  • modified:
  • reading: 2 minutes

IDN (Internationalized domain name) – это имена доменов, которые могут быть представлены в виде имени, содержащем не только латинские буквы, но и буквы других национальных алфавитов, вроде русского, арабского, китайского и т.п. (на данный момент поддерживается не так много). Представлены – это ключевое слово, так как на самом деле хранятся и передаются они в виде Punycode строк. Например, у нашей любимой почты России есть сайт http://почтароссии.рф, а Punycode представление этого сайта http://xn--80aqavbdjjaf8c.xn--p1ai/. Это важно понимать, если вы будете в запросах своего приложения (используя WebRequest, например) писать хост как IDN представление, то это имя хоста не будет распознано (если у вас не какой-нибудь специальный DNS сервер), нужно заранее переводить его в Punycode строку.

Браузер IE9, например, умеет отображать IDN представления сайтов, и даже с ними работать.

image

Chrome так же отлично работает с IDN представлениями, но отображает их сразу же в Punycode строках.

Теперь перейдем к .NET, если вы создадите простое консольное приложение, и напишите там такой код:

Uri uri = new Uri("http://почтароссии.рф/");
WebRequest wr = WebRequest.Create(uri);
WebResponse response = wr.GetResponse();
Console.WriteLine(response.ContentLength);

На этапе исполнения GetResponse вы получите ошибку System.Net.WebException: The remote name could not be resolved: 'почтароссии.рф'. Победить это очень легко, нужно всего лишь добавить поддержку IDN сайтов вашему приложению, для этого в файле app.config нужно добавить:

<configuration>
    <uri>
      <idn enabled="All"/>
    </uri>
</configuration>

После этого все будет работать. Почитать подробнее об этих настройках можно, например, на странице MSDN о Uri классе, под заголовком International Resource Identifier Support.

Но что делать, если вы пишите плагины для какого-нибудь приложения, и вы не в силах поменять глобальные параметры приложения, нет доступа, либо авторы не хотят ничего менять и править? Тут возникает сложность, так как эти параметры поддержки интернациональных доменов читаются только один раз, при первом создании объекта типа Uri, дальше изменение этих параметров уже ни на что не влияет.

В таком случае нужно делать самому кодировку IDN сайта в Punycode представление при помощи класса IdnMapping:

IdnMapping idn = new IdnMapping();
 Uri uriIdn = new Uri("http://почтароссии.рф/");
 UriBuilder uriBuilder = new UriBuilder(uriIdn);
uriBuilder.Host = idn.GetAscii(uriBuilder.Host);
 
WebRequest wr = WebRequest.Create(uriBuilder.Uri);
WebResponse response = wr.GetResponse();
Console.WriteLine(response.ContentLength);

На данный момент еще не все сервисы и не все приложения понимают IDN имена. Так, например, известный сервис Twitter не распознает ссылки, содержащие IDN имена хостов, во время написания поста (для “укорачивания” ссылки). Вы же будьте готовы ;)

See Also