Распространенной задачей при вызове веб-ресурсов из кода является построение строки запроса, включающей все необходимые параметры. Несмотря на то, что ни в коем случае не ракетостроение, есть некоторые изящные детали, о которых нужно позаботиться, например, добавление, &
если не первый параметр, кодирование параметров и т. Д.
Код для этого очень прост, но немного утомителен:
StringBuilder SB = new StringBuilder();
if (NeedsToAddParameter A)
{
SB.Append("A="); SB.Append(HttpUtility.UrlEncode("TheValueOfA"));
}
if (NeedsToAddParameter B)
{
if (SB.Length>0) SB.Append("&");
SB.Append("B="); SB.Append(HttpUtility.UrlEncode("TheValueOfB")); }
}
Это такая распространенная задача, что можно ожидать существования служебного класса, который делает его более элегантным и читаемым. Сканируя MSDN, я не смог найти ни одного, что приводит меня к следующему вопросу:
Какой самый элегантный и чистый способ сделать это?
c#
.net
url
query-string
Боаз
источник
источник
Ответы:
Если вы заглянете внутрь, свойство QueryString будет NameValueCollection. Когда я делал подобные вещи, я обычно интересовался сериализацией и десериализацией, поэтому я предлагаю создать коллекцию NameValueCollection и затем перейти к:
Я думаю, что в LINQ тоже есть супер элегантный способ сделать это ...
источник
application/x-www-form-urlencoded
и фактически определяется HTML с целью отправки данных формы как частиGET
запроса. HTML 5 не запрещает использование нескольких значений на ключ в этом формате и фактически требует, чтобы браузер выдавал несколько значений на ключ в случае, если страница (неправильно) содержит несколько полей с одним и тем жеname
атрибутом. Смотрите goo.gl/uk1AgВы можете создать новый доступный для записи экземпляр
HttpValueCollection
, вызвав егоSystem.Web.HttpUtility.ParseQueryString(string.Empty)
, а затем использовать его как любойNameValueCollection
. После того, как вы добавили нужные значения, вы можете вызватьToString
коллекцию, чтобы получить строку запроса, как показано ниже:Он
HttpValueCollection
является внутренним, и поэтому вы не можете напрямую создать экземпляр. Однако, как только вы получите экземпляр, вы можете использовать его, как и любой другойNameValueCollection
. Поскольку фактический объект, с которым вы работаете, - этоHttpValueCollection
метод, вызов метода ToString вызовет переопределенный методHttpValueCollection
, который форматирует коллекцию как строку запроса в кодировке URL.После поиска SO и в Интернете ответа на похожую проблему, это самое простое решение, которое я мог найти.
.NET Core
Если вы работаете в .NET Core, вы можете использовать этот
Microsoft.AspNetCore.WebUtilities.QueryHelpers
класс, что значительно упрощает это.https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.webutilities.queryhelpers
Образец кода:
источник
public static string ToURLQueryString(this IDictionary dict) { ... }
Add
метод. Т.е.queryString.Add("type", "1"); queryString.Add("type", "2");
использованиеAdd
метода, вероятно, является лучшим способом сделать это все время на самом деле.Вдохновленный комментариями Роя Тинкера, я использовал простой метод расширения класса Uri, который делает мой код лаконичным и чистым:
Применение:
Редактировать - Соответствующий стандартам вариант
Как отметили несколько человек,
httpValueCollection.ToString()
кодирует символы Unicode нестандартным способом. Это вариант того же метода расширения, который обрабатывает такие символы, вызываяHttpUtility.UrlEncode
метод вместо устаревшегоHttpUtility.UrlEncodeUnicode
метода.источник
Я ответил на аналогичный вопрос некоторое время назад. По сути, лучшим способом было бы использовать класс
HttpValueCollection
, которым наRequest.QueryString
самом деле является свойство ASP.NET , к сожалению, оно является внутренним в среде .NET. Вы можете использовать Reflector, чтобы захватить его (и поместить в свой класс Utils). Таким образом, вы можете манипулировать строкой запроса, например, NameValueCollection, но со всеми проблемами кодирования / декодирования URL позаботились о вас.HttpValueCollection
расширяетсяNameValueCollection
и имеет конструктор, который принимает закодированную строку запроса (включая амперсанды и вопросительные знаки) и переопределяетToString()
метод для последующего перестроения строки запроса из базовой коллекции.Пример:
источник
httpValueCollection.ToString()
на самом деле звонки,httpValueCollection.ToString(true)
так что добавлениеtrue
простоты не требуется.Вот беглый / лямбда-выход в качестве метода расширения (объединение понятий в предыдущих статьях), который поддерживает несколько значений для одного и того же ключа. Мое личное предпочтение - расширение над оболочками для возможности обнаружения другими членами команды для подобных вещей. Обратите внимание, что существуют противоречия по поводу методов кодирования, об этом много публикаций о переполнении стека (одна такая публикация ) и блоггерах MSDN (как эта ).
edit: с нулевой поддержкой, хотя вам, вероятно, придется адаптировать ее для вашей конкретной ситуации
источник
Flurl [раскрытие: я автор] поддерживает создание строк запроса через анонимные объекты (среди прочих способов):
Необязательная сопутствующая библиотека Flurl.Http позволяет вам выполнять HTTP-вызовы сразу из одной и той же цепочки быстрых вызовов, расширяя ее до полноценного REST-клиента:
Полный пакет доступен на NuGet:
PM> Install-Package Flurl.Http
или просто автономный построитель URL:
PM> Install-Package Flurl
источник
Вот моя поздняя запись. Мне не нравились другие по разным причинам, поэтому я написал свою.
Эта версия имеет:
Использование только StringBuilder. Нет вызовов ToArray () или других методов расширения. Это выглядит не так красиво, как некоторые другие ответы, но я считаю, что это основная функция, поэтому эффективность важнее, чем наличие «беглого», «однострочного» кода, который скрывает неэффективность.
Обрабатывает несколько значений на ключ. (Не нужно было это самому, но чтобы заставить замолчать Маурисио;)
Пример использования
Вывод
источник
Как насчет создания методов расширения, которые позволяют вам добавлять параметры в свободном стиле, как это?
Вот перегрузка, которая использует
string
:И вот перегрузка, которая использует
StringBuilder
:источник
NameValueCollection
,HttpValueCollection
илиUri
первый. Спасибо!Мне нужно было решить ту же проблему для переносимой библиотеки классов (PCL), над которой я работаю. В этом случае у меня нет доступа к System.Web, поэтому я не могу использовать ParseQueryString.
Вместо этого я использовал
System.Net.Http.FormUrlEncodedContent
так:источник
источник
.ToArray()
с.Добавьте этот класс в ваш проект
И используйте это так:
источник
Моя жертва:
Применение:
источник
Не проверено, но я думаю, что что-то в этом роде будет работать очень хорошо
источник
Версия на основе метода быстрого расширения:
Вы можете использовать предложение where, чтобы выбрать, какие параметры будут добавлены в строку.
источник
Предполагая, что вы хотите уменьшить зависимости от других сборок и упростить задачу, вы можете сделать следующее:
Это хорошо работает и с петлями. Окончательное удаление амперсанда должно выходить за пределы цикла.
Обратите внимание, что оператор конкатенации используется для улучшения читабельности. Стоимость его использования по сравнению со стоимостью использования StringBuilder минимальна (я думаю, что Джефф Этвуд опубликовал что-то на эту тему).
источник
Комбинировал верхние ответы для создания анонимной версии объекта :
Это создает это:
Вот код:
источник
То же, что и принятое решение, но переведено в синтаксис LINQ "точка" ...
источник
У меня есть метод расширения для Uri, который:
uri.WithQuery(new { name = "value" })
string/string
пар (например, Dictionary`2 ).string/object
пар (например, RouteValueDictionary ).Документированная версия может быть найдена здесь .
Расширение:
Парсер запросов:
Вот тесты:
источник
Цепной класс-оболочка для HttpValueCollection:
Пример использования:
источник
Я добавил следующий метод в свой класс PageBase.
Звонить:
источник
Я написал несколько методов расширения, которые я нашел очень полезными при работе с QueryStrings. Часто я хочу начать с текущей строки QueryString и изменить ее перед использованием. Что-то вроде,
Для получения дополнительной информации и источника: http://www.charlesrcook.com/archive/2008/07/23/c-extension-methods-for-asp.net-query-string-operations.aspx
Это простой, но мне нравится стиль.
источник
Просто хотел скинуть 2 моих цента
Документы говорят, что
uri.Query
начнется с?
если он не пустой, и вы должны обрезать его, если вы собираетесь изменить его.Обратите внимание, что
HttpUtility.UrlEncode
находится вSystem.Web
.Применение:
источник
Хотя это и не элегантно, я выбрал более простую версию, которая не использует
NameValueCollecitons
- просто шаблон построителя, обернутый вокругStringBuilder
.Согласно существующим ответам, я убедился, что использовал
HttpUtility.UrlEncode
звонки. Используется так:источник
Вывод:
Код; Вы все можете поблагодарить меня где-нибудь, как-то: D
источник
Я пошел с решением, предложенным DSO (ответ 2 августа 2011 года в 7:29), его решение не требует использования HttpUtility. Однако, согласно статье, опубликованной в Dotnetpearls , использование словаря быстрее (по производительности), чем использование NameValueCollection. Вот решение DSO, измененное для использования словаря вместо NameValueCollection.
источник
Строка запроса может быть добавлена в URL:
https://blog.codingnovice.com/blog
источник
Я написал помощника для моего проекта бритвы, используя некоторые подсказки из других ответов.
Бизнес ParseQueryString необходим, потому что нам не разрешено вмешиваться в объект QueryString текущего запроса.
Я использую это так:
Если вы хотите, чтобы оно принимало более одного значения, просто измените параметры на словарь и добавьте пары в строку запроса.
источник
Приведенный ниже код снят с
HttpValueCollection
реализацииToString
через ILSpy, который дает вам строку запроса name = value.К сожалению, HttpValueCollection является внутренним классом, который вы можете получить только в случае использования
HttpUtility.ParseQueryString()
. Я удалил все части viewstate к нему, и он кодирует по умолчанию:источник
Это идентично принятому ответу, за исключением чуть более компактного:
источник
Просто для тех, кому нужна VB.NET-версия топ-ответа:
И версия без LINQ:
И версия C # без LINQ:
источник