Если я хочу отправить запрос http get с помощью System.Net.HttpClient, кажется, что нет api для добавления параметров, это правильно?
Есть ли простой API, доступный для создания строки запроса, которая не включает создание коллекции значений имени и URL, кодирующих их, а затем, наконец, объединяет их? Я надеялся использовать что-то вроде API RestSharp (т.е. AddParameter (..))
Ответы:
Да.
Конечно:
даст вам ожидаемый результат:
Вы также можете найти
UriBuilder
класс полезным:даст вам ожидаемый результат:
что вы могли бы более чем безопасно кормить свой
HttpClient.GetAsync
метод.источник
#
), используя свойство Fragment. Я видел, как многие люди совершали ошибку, обрабатывая URL-адреса вручную вместо использования встроенных инструментов.NameValueCollection.ToString()
как правило , не делает запрос строки, и нет никакой документации о том , что делатьToString
в результатеParseQueryString
приведет к новой строке запроса, таким образом , может сломаться в любое время , поскольку нет никакой гарантии в том , что функциональность.Для тех, кто не хочет включать
System.Web
в проекты, которые еще не используют его, вы можете использоватьFormUrlEncodedContent
изSystem.Net.Http
и сделать что-то вроде следующего:версия ключевой пары
словарная версия
источник
dispose
? Я всегда выбрасывайте , если у меня есть веские причины не делать этого , как повторное использованиеHttpClient
.TL; DR: не использовать принятую версию, так как она полностью не работает с обработкой символов Юникода и никогда не использует внутренний API
На самом деле я обнаружил странную проблему двойного кодирования с принятым решением:
Итак, если вы имеете дело с символами, которые необходимо кодировать, то принятое решение приводит к двойному кодированию:
NameValueCollection
индексатора ( и это используетUrlEncodeUnicode
, а не обычное ожиданиеUrlEncode
(!) )uriBuilder.Uri
он создает новыйUri
конструктор using, который выполняет кодирование еще раз (обычное кодирование URL).uriBuilder.ToString()
(даже если это вернёт правильно,Uri
что IMO - это как минимум несоответствие, может быть, ошибка, но это другой вопрос), а затем с помощьюHttpClient
метода, принимающего строку - клиент все равно создаетUri
из переданной вами строки вот так:new Uri(uri, UriKind.RelativeOrAbsolute)
Небольшое, но полное воспроизведение:
Вывод:
Как вы можете видеть, независимо от того, что вы делаете
uribuilder.ToString()
+httpClient.GetStringAsync(string)
илиuriBuilder.Uri
+,httpClient.GetStringAsync(Uri)
вы в конечном итоге отправляете двойной кодированный параметрИсправленный пример может быть:
Но это использует устаревший
Uri
конструкторPS в моем последнем .NET на Windows Server
Uri
конструктор с комментарием bool doc говорит: «устарел, dontEscape всегда ложен», но на самом деле работает как положено (пропускает экранирование)Так что похоже на еще одну ошибку ...
И даже это совершенно неправильно - он отправляет UrlEncodedUnicode на сервер, а не только UrlEncoded, что ожидает сервер
Обновление: еще одна вещь, NameValueCollection фактически делает UrlEncodeUnicode, который больше не должен использоваться и несовместим с обычным url.encode / decode (см. NameValueCollection для URL Query? ).
Итак, суть в том, что никогда не используйте этот хак,
NameValueCollection query = HttpUtility.ParseQueryString(builder.Query);
поскольку он испортит параметры вашего запроса в Юникоде. Просто создайте запрос вручную и назначьте его,UriBuilder.Query
который будет выполнять необходимую кодировку, а затем получите Uri, используяUriBuilder.Uri
.Яркий пример причинения себе вреда при использовании кода, который не должен использоваться таким образом
источник
var namedValues = HttpUtility.ParseQueryString(builder.Query)
решением этой проблемы является использование , но затем вместо использования возвращенного NameValueCollection немедленно преобразуйте его в словарь следующим образом:var dic = values.ToDictionary(x => x, x => values[x]);
добавьте новые значения в словарь, затем передайте его конструкторуFormUrlEncodedContent
и вызовитеReadAsStringAsync().Result
его. Это дает вам правильно закодированную строку запроса, которую вы можете назначить обратно UriBuilder.<add key="aspnet:DontUsePercentUUrlEncoding" value="true" />
. Я бы не зависел от этого поведения, поэтому лучше использовать класс FormUrlEncodedContent, как показано в предыдущем ответе: stackoverflow.com/a/26744471/88409В проекте ASP.NET Core вы можете использовать класс QueryHelpers.
источник
Возможно, вы захотите проверить Flurl [раскрытие: я автор], беглый конструктор URL с опциональной дополнительной библиотекой, которая расширяет его до полноценного REST-клиента.
Проверьте документы для более подробной информации. Полный пакет доступен на NuGet:
PM> Install-Package Flurl.Http
или просто автономный построитель URL:
PM> Install-Package Flurl
источник
Uri
или начать с вашего собственного класса вместоstring
?Url
класса. Вышесказанное эквивалентноnew Url("https://api.com").AppendPathSegment...
Лично я предпочитаю расширения строк из-за меньшего количества нажатий клавиш и стандартизированы на них в документах, но вы можете сделать это в любом случае.По аналогии с постом Ростова, если вы не хотите включать ссылку
System.Web
в свой проект, вы можете использоватьFormDataCollection
fromSystem.Net.Http.Formatting
и сделать что-то вроде следующего:С помощью
System.Net.Http.Formatting.FormDataCollection
источник
Дарин предложил интересное и умное решение, и вот что может быть другим вариантом:
и поэтому, используя его, вы можете сделать это:
источник
kvp.Key
иkvp.Value
отдельно внутри цикла for, а не в полной строке запроса (таким образом, не кодируя&
, а=
символы).server.UrlEncode
можно заменить наWebUtility.UrlEncode
Или просто используя мое расширение Uri
Код
использование
результат
источник
RFC 6570 URI Библиотека шаблонов Я разрабатываю способен выполнять эту операцию. Вся кодировка обрабатывается для вас в соответствии с этим RFC. На момент написания этой статьи доступна бета-версия, и единственная причина, по которой она не считается стабильной версией 1.0, заключается в том, что документация не полностью соответствует моим ожиданиям (см. Проблемы № 17 , № 18 , № 32 , № 43 ).
Вы можете создать только строку запроса:
Или вы можете создать полный URI:
источник
Поскольку мне пришлось использовать это немного раз, я придумал этот класс, который просто помогает абстрагироваться от составления строки запроса.
Использование будет упрощено до чего-то вроде этого:
который вернет URI: http://example.com/?foo=bar%3c%3e%26-baz&bar=second
источник
Чтобы избежать проблемы двойного кодирования, описанной в ответе taras.roshko, и сохранить возможность легко работать с параметрами запроса, вы можете использовать
uriBuilder.Uri.ParseQueryString()
вместоHttpUtility.ParseQueryString()
.источник
Хорошая часть принятого ответа, измененная для использования UriBuilder.Uri.ParseQueryString () вместо HttpUtility.ParseQueryString ():
источник
ParseQueryString()
метод расширения находится за пределамиSystem
.Благодаря «Дарину Димитрову», это методы расширения.
источник
Я не мог найти лучшего решения, чем создание метода расширения для преобразования словаря в QueryStringFormat. Решение, предложенное Waleed AK, также хорошо.
Следуйте моему решению:
Создайте метод расширения:
И им:
источник