将值附加到查询string

我有一组类似于下面的列表中的URL

  • http://somesite.com/backup/lol.php?id=1&server=4&location=us
  • http://somesite.com/news.php?article=1&lang=en

我设法使用下面的代码获取查询string:

myurl = longurl.Split('?'); NameValueCollection qs = HttpUtility.ParseQueryString(myurl [1]); foreach (string lol in qs) { // results will return } 

但是它只会根据提供的URL返回idserverlocation等参数。

我需要的是添加/附加值到现有的查询string。

例如与URL:

http://somesite.com/backup/index.php?action=login&attempts=1

我需要改变查询string参数的值:

行动= login1

尝试= 11

正如你所看到的,我为每个值附加了“1”。 我需要从一个string中获取一组不同的查询string的URL,并在每个参数的末尾添加一个值,再次将它们添加到列表中。

你可以使用HttpUtility.ParseQueryString方法和一个UriBuilder ,它提供了一个很好的方式来处理查询string参数,而不用担心诸如parsing,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" 

我把Darin的答案包装成一个很好的可重用的扩展方法。

 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会有问题的原因当涉及到查询操作。

这是一个解决方法,适用于绝对path和相对path,在.NET 4中编写和testing:

(小注:这也应该在.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&amp;param2=val2&amp;param3=val3" /// new Uri("www.domain.com/test?param1=val1").ExtendQuery(new Dictionary&lt;string, string&gt; { { "param2", "val2" }, { "param3", "val3" } }); /// /// // returns "/test?param1=val1&amp;param2=val2&amp;param3=val3" /// new Uri("/test?param1=val1").ExtendQuery(new Dictionary&lt;string, string&gt; { { "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&amp;param2=val2&amp;param3=val3" /// new Uri("www.domain.com/test?param1=val1").ExtendQuery(new { param2 = "val2", param3 = "val3" }); /// /// // returns "/test?param1=val1&amp;param2=val2&amp;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; } )); } } 

这里有一套unit testing来testing行为:

  [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&param2=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&param2=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&param2=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&param2=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&param2=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&param2=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&param2=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&param2=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&param2=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&param2=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&param2=val2", UriKind.Relative))); } } 

以下解决scheme适用于ASP.NET 5(vNext),它使用QueryHelpers类来构build带有参数的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&param2=value2&param3=value3

我喜欢比约恩的回答,但是他提供的解决scheme是误导性的,因为方法更新了现有的参数,而不是在不存在的情况下添加它。为了使它更安全一点,我在下面进行了调整。

 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; } } 

所有的URL查询string编辑困境的结束

经过大量的努力和Uri类的摆弄,以及其他解决scheme,这里是我的string扩展方法来解决我的问题。

 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; } }