Append values to query string

后端 未结 8 1485
借酒劲吻你
借酒劲吻你 2020-11-28 20:32

I have set of URL\'s similar to the ones below in a list

  • http://somesite.com/backup/lol.php?id=1&server=4&location=us
  • http://somesite.com/news
8条回答
  •  醉话见心
    2020-11-28 20:52

    The provided answers have issues with relative Url's, such as "/some/path/" This is a limitation of the Uri and UriBuilder class, which is rather hard to understand, since I don't see any reason why relative urls would be problematic when it comes to query manipulation.

    Here is a workaround that works for both absolute and relative paths, written and tested in .NET 4:

    (small note: this should also work in .NET 4.5, you will only have to change propInfo.GetValue(values, null) to propInfo.GetValue(values))

      public static class UriExtensions{
        /// 
        ///     Adds query string value to an existing url, both absolute and relative URI's are supported.
        /// 
        /// 
        /// 
        ///     // 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" } }); 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static Uri ExtendQuery(this Uri uri, IDictionary 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()) {
            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);
        }
    
        /// 
        ///     Adds query string value to an existing url, both absolute and relative URI's are supported.
        /// 
        /// 
        /// 
        ///     // 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" }); 
        /// 
        /// 
        /// 
        /// 
        /// 
        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; }
          ));
        }
      }
    

    And here is a suite of unit tests to test the behavior:

      [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();
          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();
          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 { { "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 { { "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 { { "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 { { "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 { { "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 { { "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)));
        }
      }
    

提交回复
热议问题