Добавление значений в строку запроса
У меня есть набор URL-адресов, подобных приведенным ниже в списке
- http://somesite.com/backup/lol.php?id=1&server=4&location=us
- http://somesite.com/news.php?article=1&lang=en
мне удалось получить строку запроса, используя следующий код:
myurl = longurl.Split('?');
NameValueCollection qs = HttpUtility.ParseQueryString(myurl [1]);
foreach (string lol in qs)
{
// results will return
}
но он возвращает только такие параметры, как id,сервер, location и так далее на основе предоставленного URL.
Мне нужно добавить / добавить значения в существующие строки запроса.
например, с URL:
http://somesite.com/backup/index.php?action=login&attempts=1
Мне нужно изменить значения параметров строки запроса:
действие= "имя_входа1"
попытки=11
Как вы можете видеть, я добавил "1" для каждого значения. Мне нужно чтобы получить набор URL-адресов из строки с разными строками запроса в них и добавить значение к каждому параметру в конце и снова добавить их в список.
8 ответов:
можно использовать
HttpUtility.ParseQueryString
способ иUriBuilder
что обеспечивает хороший способ работы с параметрами строки запроса, не беспокоясь о таких вещах, как разбор, кодирование url,...:string longurl = "http://somesite.com/news.php?article=1&lang=en"; var uriBuilder = new UriBuilder(longurl); var query = HttpUtility.ParseQueryString(uriBuilder.Query); query["action"] = "login1"; query["attempts"] = "11"; uriBuilder.Query = query.ToString(); longurl = uriBuilder.ToString(); // "http://somesite.com:80/news.php?article=1&lang=en&action=login1&attempts=11"
я завернул ответ Дарина В красиво многоразовый метод расширения.
public static class UriExtensions { /// <summary> /// Adds the specified parameter to the Query String. /// </summary> /// <param name="url"></param> /// <param name="paramName">Name of the parameter to add.</param> /// <param name="paramValue">Value for the parameter to add.</param> /// <returns>Url with added parameter.</returns> public static Uri AddParameter(this Uri url, string paramName, string paramValue) { var uriBuilder = new UriBuilder(url); var query = HttpUtility.ParseQueryString(uriBuilder.Query); query[paramName] = paramValue; uriBuilder.Query = query.ToString(); return uriBuilder.Uri; } }
надеюсь, это поможет!
предоставленные ответы имеют проблемы с относительными Url-адресами, такими как " /some / path/" Это ограничение класса Uri и UriBuilder, которое довольно трудно понять, поскольку я не вижу причин, по которым относительные URL-адреса будут проблематичными, когда речь заходит о манипуляциях с запросами.
вот обходной путь, который работает как для абсолютных, так и для относительных путей, написанных и протестированных в .NET 4:
(небольшое примечание: это также должно работать в .NET 4.5, вам нужно будет только изменить
propInfo.GetValue(values, null)
доpropInfo.GetValue(values)
)public static class UriExtensions{ /// <summary> /// Adds query string value to an existing url, both absolute and relative URI's are supported. /// </summary> /// <example> /// <code> /// // returns "www.domain.com/test?param1=val1&param2=val2&param3=val3" /// new Uri("www.domain.com/test?param1=val1").ExtendQuery(new Dictionary<string, string> { { "param2", "val2" }, { "param3", "val3" } }); /// /// // returns "/test?param1=val1&param2=val2&param3=val3" /// new Uri("/test?param1=val1").ExtendQuery(new Dictionary<string, string> { { "param2", "val2" }, { "param3", "val3" } }); /// </code> /// </example> /// <param name="uri"></param> /// <param name="values"></param> /// <returns></returns> public static Uri ExtendQuery(this Uri uri, IDictionary<string, string> values) { var baseUrl = uri.ToString(); var queryString = string.Empty; if (baseUrl.Contains("?")) { var urlSplit = baseUrl.Split('?'); baseUrl = urlSplit[0]; queryString = urlSplit.Length > 1 ? urlSplit[1] : string.Empty; } NameValueCollection queryCollection = HttpUtility.ParseQueryString(queryString); foreach (var kvp in values ?? new Dictionary<string, string>()) { queryCollection[kvp.Key] = kvp.Value; } var uriKind = uri.IsAbsoluteUri ? UriKind.Absolute : UriKind.Relative; return queryCollection.Count == 0 ? new Uri(baseUrl, uriKind) : new Uri(string.Format("{0}?{1}", baseUrl, queryCollection), uriKind); } /// <summary> /// Adds query string value to an existing url, both absolute and relative URI's are supported. /// </summary> /// <example> /// <code> /// // returns "www.domain.com/test?param1=val1&param2=val2&param3=val3" /// new Uri("www.domain.com/test?param1=val1").ExtendQuery(new { param2 = "val2", param3 = "val3" }); /// /// // returns "/test?param1=val1&param2=val2&param3=val3" /// new Uri("/test?param1=val1").ExtendQuery(new { param2 = "val2", param3 = "val3" }); /// </code> /// </example> /// <param name="uri"></param> /// <param name="values"></param> /// <returns></returns> public static Uri ExtendQuery(this Uri uri, object values) { return ExtendQuery(uri, values.GetType().GetProperties().ToDictionary ( propInfo => propInfo.Name, propInfo => { var value = propInfo.GetValue(values, null); return value != null ? value.ToString() : null; } )); } }
а вот набор модульных тестов для проверки поведения:
[TestFixture] public class UriExtensionsTests { [Test] public void Add_to_query_string_dictionary_when_url_contains_no_query_string_and_values_is_empty_should_return_url_without_changing_it() { Uri url = new Uri("http://www.domain.com/test"); var values = new Dictionary<string, string>(); var result = url.ExtendQuery(values); Assert.That(result, Is.EqualTo(new Uri("http://www.domain.com/test"))); } [Test] public void Add_to_query_string_dictionary_when_url_contains_hash_and_query_string_values_are_empty_should_return_url_without_changing_it() { Uri url = new Uri("http://www.domain.com/test#div"); var values = new Dictionary<string, string>(); var result = url.ExtendQuery(values); Assert.That(result, Is.EqualTo(new Uri("http://www.domain.com/test#div"))); } [Test] public void Add_to_query_string_dictionary_when_url_contains_no_query_string_should_add_values() { Uri url = new Uri("http://www.domain.com/test"); var values = new Dictionary<string, string> { { "param1", "val1" }, { "param2", "val2" } }; var result = url.ExtendQuery(values); Assert.That(result, Is.EqualTo(new Uri("http://www.domain.com/test?param1=val1¶m2=val2"))); } [Test] public void Add_to_query_string_dictionary_when_url_contains_hash_and_no_query_string_should_add_values() { Uri url = new Uri("http://www.domain.com/test#div"); var values = new Dictionary<string, string> { { "param1", "val1" }, { "param2", "val2" } }; var result = url.ExtendQuery(values); Assert.That(result, Is.EqualTo(new Uri("http://www.domain.com/test#div?param1=val1¶m2=val2"))); } [Test] public void Add_to_query_string_dictionary_when_url_contains_query_string_should_add_values_and_keep_original_query_string() { Uri url = new Uri("http://www.domain.com/test?param1=val1"); var values = new Dictionary<string, string> { { "param2", "val2" } }; var result = url.ExtendQuery(values); Assert.That(result, Is.EqualTo(new Uri("http://www.domain.com/test?param1=val1¶m2=val2"))); } [Test] public void Add_to_query_string_dictionary_when_url_is_relative_contains_no_query_string_should_add_values() { Uri url = new Uri("/test", UriKind.Relative); var values = new Dictionary<string, string> { { "param1", "val1" }, { "param2", "val2" } }; var result = url.ExtendQuery(values); Assert.That(result, Is.EqualTo(new Uri("/test?param1=val1¶m2=val2", UriKind.Relative))); } [Test] public void Add_to_query_string_dictionary_when_url_is_relative_and_contains_query_string_should_add_values_and_keep_original_query_string() { Uri url = new Uri("/test?param1=val1", UriKind.Relative); var values = new Dictionary<string, string> { { "param2", "val2" } }; var result = url.ExtendQuery(values); Assert.That(result, Is.EqualTo(new Uri("/test?param1=val1¶m2=val2", UriKind.Relative))); } [Test] public void Add_to_query_string_dictionary_when_url_is_relative_and_contains_query_string_with_existing_value_should_add_new_values_and_update_existing_ones() { Uri url = new Uri("/test?param1=val1", UriKind.Relative); var values = new Dictionary<string, string> { { "param1", "new-value" }, { "param2", "val2" } }; var result = url.ExtendQuery(values); Assert.That(result, Is.EqualTo(new Uri("/test?param1=new-value¶m2=val2", UriKind.Relative))); } [Test] public void Add_to_query_string_object_when_url_contains_no_query_string_should_add_values() { Uri url = new Uri("http://www.domain.com/test"); var values = new { param1 = "val1", param2 = "val2" }; var result = url.ExtendQuery(values); Assert.That(result, Is.EqualTo(new Uri("http://www.domain.com/test?param1=val1¶m2=val2"))); } [Test] public void Add_to_query_string_object_when_url_contains_query_string_should_add_values_and_keep_original_query_string() { Uri url = new Uri("http://www.domain.com/test?param1=val1"); var values = new { param2 = "val2" }; var result = url.ExtendQuery(values); Assert.That(result, Is.EqualTo(new Uri("http://www.domain.com/test?param1=val1¶m2=val2"))); } [Test] public void Add_to_query_string_object_when_url_is_relative_contains_no_query_string_should_add_values() { Uri url = new Uri("/test", UriKind.Relative); var values = new { param1 = "val1", param2 = "val2" }; var result = url.ExtendQuery(values); Assert.That(result, Is.EqualTo(new Uri("/test?param1=val1¶m2=val2", UriKind.Relative))); } [Test] public void Add_to_query_string_object_when_url_is_relative_and_contains_query_string_should_add_values_and_keep_original_query_string() { Uri url = new Uri("/test?param1=val1", UriKind.Relative); var values = new { param2 = "val2" }; var result = url.ExtendQuery(values); Assert.That(result, Is.EqualTo(new Uri("/test?param1=val1¶m2=val2", UriKind.Relative))); } [Test] public void Add_to_query_string_object_when_url_is_relative_and_contains_query_string_with_existing_value_should_add_new_values_and_update_existing_ones() { Uri url = new Uri("/test?param1=val1", UriKind.Relative); var values = new { param1 = "new-value", param2 = "val2" }; var result = url.ExtendQuery(values); Assert.That(result, Is.EqualTo(new Uri("/test?param1=new-value¶m2=val2", UriKind.Relative))); } }
следующее решение работает для ASP.NET 5 (vNext) и он использует класс QueryHelpers для построения URI с параметрами.
public Uri GetUri() { var location = _config.Get("http://iberia.com"); Dictionary<string, string> values = GetDictionaryParameters(); var uri = Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString(location, values); return new Uri(uri); } private Dictionary<string,string> GetDictionaryParameters() { Dictionary<string, string> values = new Dictionary<string, string> { { "param1", "value1" }, { "param2", "value2"}, { "param3", "value3"} }; return values; }
результат URI будет иметь
http://iberia.com?param1=value1¶m2=value2¶m3=value3
Примечание Вы можете добавить
Microsoft.AspNetCore.WebUtilities
пакет nuget от Microsoft, а затем используйте его для добавления значений в строку запроса:QueryHelpers.AddQueryString(longurl, "action", "login1") QueryHelpers.AddQueryString(longurl, new Dictionary<string, string> { { "action", "login1" }, { "attempts", "11" } });
конец всех бед редактирования строки запроса URL
после большого труда и возни с классом Uri и другими решениями, вот мой строка методы расширения для решения моих проблем.
using System; using System.Collections.Specialized; using System.Linq; using System.Web; public static class StringExtensions { public static string AddToQueryString(this string url, params object[] keysAndValues) { return UpdateQueryString(url, q => { for (var i = 0; i < keysAndValues.Length; i += 2) { q.Set(keysAndValues[i].ToString(), keysAndValues[i + 1].ToString()); } }); } public static string RemoveFromQueryString(this string url, params string[] keys) { return UpdateQueryString(url, q => { foreach (var key in keys) { q.Remove(key); } }); } public static string UpdateQueryString(string url, Action<NameValueCollection> func) { var urlWithoutQueryString = url.Contains('?') ? url.Substring(0, url.IndexOf('?')) : url; var queryString = url.Contains('?') ? url.Substring(url.IndexOf('?')) : null; var query = HttpUtility.ParseQueryString(queryString ?? string.Empty); func(query); return urlWithoutQueryString + (query.Count > 0 ? "?" : string.Empty) + query; } }
Мне нравится ответ Бьорна, однако решение, которое он предоставил, вводит в заблуждение, поскольку метод обновляет существующий параметр, а не добавляет его, если он не существует.. Чтобы сделать его немного безопаснее, я адаптировал его ниже.
public static class UriExtensions { /// <summary> /// Adds or Updates the specified parameter to the Query String. /// </summary> /// <param name="url"></param> /// <param name="paramName">Name of the parameter to add.</param> /// <param name="paramValue">Value for the parameter to add.</param> /// <returns>Url with added parameter.</returns> public static Uri AddOrUpdateParameter(this Uri url, string paramName, string paramValue) { var uriBuilder = new UriBuilder(url); var query = HttpUtility.ParseQueryString(uriBuilder.Query); if (query.AllKeys.Contains(paramName)) { query[paramName] = paramValue; } else { query.Add(paramName, paramValue); } uriBuilder.Query = query.ToString(); return uriBuilder.Uri; } }
мой подход очень прост, для начинающих:
// --> Prototype : https://ctrader.guru/?id=1#reload public static string AddGetParamToUrl(string url, string pname, string pvalue) { pvalue = Uri.EscapeDataString(pvalue); if (url.IndexOf("?") > -1) { url = url.Replace("?", string.Format("?{0}={1}&", pname, pvalue)); } else if (url.IndexOf("#") > -1) { url = url.Replace("#", string.Format("?{0}={1}#", pname, pvalue)); } else { url = string.Format("{0}?{1}={2}", url, pname, pvalue); } return url; }