Буквальные амперсанды в строке запроса System.Uri - PullRequest
4 голосов
/ 20 мая 2010

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

Однако всякий раз, когда я передаю% 26 (URI экранированный символ амперсанда) в System.Uri, он преобразует его обратно в обычный символ амперсанда! При ближайшем рассмотрении единственными двумя символами, которые не преобразованы обратно, являются хеш (% 23) и процент (% 25).

Допустим, я хочу найти компанию под названием "Pierce & Pierce":

var endPoint = "http://localhost/companies?where=Name eq '{0}'";
var name = "Pierce & Pierce";
Console.WriteLine(new Uri(string.Format(endPoint, name)));
Console.WriteLine(new Uri(string.Format(endPoint, name.Replace("&", "%26"))));
Console.WriteLine(new Uri(string.Format(endPoint, Uri.EscapeUriString(name))));
Console.WriteLine(new Uri(string.Format(endPoint, Uri.EscapeDataString(name))));

Возвращаются все четыре из вышеперечисленных комбинаций:

http://localhost/companies?where=Name eq 'Pierce & Pierce'

Это приводит к ошибкам на стороне сервера, поскольку амперсанд (правильно) интерпретируется как разделитель аргументов запроса. Мне действительно нужно вернуть исходную строку:

http://localhost/companies?where=Name eq 'Pierce %26 Pierce'

Как я могу обойти это поведение, не отбрасывая System.Uri полностью? Я не могу заменить все амперсанды на% 26 в последний момент, потому что обычно используется несколько аргументов запроса, и я не хочу уничтожать их разделители.

Примечание: Подобная проблема обсуждалась в в этом вопросе , но я специально имею в виду System.Uri.

Ответы [ 3 ]

10 голосов
/ 20 мая 2010

Не только амперсанд неверен в URL. Действительный URL не может содержать пробелов.

Метод EscapeDataString прекрасно работает для правильного кодирования строки, и вы должны кодировать все значение, а не только имя:

Uri.EscapeDataString("Name eq 'Pierce & Pierce'")

Результат:

Name%20eq%20'Pierce%20%26%20Pierce'

Когда вы создадите Uri, используя эту строку, она будет правильной. Для просмотра URL вы можете использовать свойство AbsoluteUri. Если вы просто конвертируете Uri в строку (которая вызывает метод ToString), URL-адрес не будет экранирован и, следовательно, будет отображаться неправильно.

0 голосов
/ 15 июня 2010

Я решил эту проблему, создав производный класс Uri

    class Uri2 : System.Uri
{
    public Uri2(string url) : base(url)
    {
    }

    public override string ToString()
    {
        return AbsoluteUri;
    }
}

В любом месте, где используется System.Uri, используйте замененный Uri2. Я не знаю, является ли это ошибкой .NetCF, WebBrowser должен отправлять URL в закодированном формате, то есть значение AbsoluteUri, но не значение из ToString ()

0 голосов
/ 15 июня 2010

У меня такая же проблема. Хотя строка запроса экранируется с помощью Uri.EscapeDataString, а свойство AbsoluteUri правильно отображает его, но WebBrowser отправляет Uri в неэкранированном формате.

  currentUri = new System.Uri(ServerAgent.urlBase + "/MailRender?uid="
+ Uri.EscapeDataString(uid);

webBrowser.Navigate (currentUri);

Знак плюс ('+') преобразуется в% 2B, но сервер все равно получает + в URL, который затем преобразуется в пробел ('') с помощью вызова HttpServeletRequest.getParameter ()

...