Sorgu dizesine değerler ekleme


162

Bir listede aşağıdaki URL'lere benzer URL'ler kümesi var

Aşağıdaki kodu kullanarak sorgu dizeleri almayı başardılar:

myurl = longurl.Split('?');
NameValueCollection qs = HttpUtility.ParseQueryString(myurl [1]);

foreach (string lol in qs)
{
    // results will return
}

Ancak, yalnızca sağlanan URL'ye göre id , sunucu , konum vb. Parametreleri döndürür .

Ne gerek var / varolan sorgu dizeleri değerleri eklemek.

Örneğin, URL ile:

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

Sorgu dizesi parametrelerinin değerlerini değiştirmek gerekir:

aksiyon = Login1

girişimleri = 11

Gördüğünüz gibi, her değer için "1" ekledim. URL bir dizi onları farklı sorgu dizeleri ile bir dizeden almak ve sonunda her parametreye bir değer eklemek ve tekrar bir listeye eklemek gerekir.

Yanıtlar:


329

Sen kullanabilirsiniz HttpUtility.ParseQueryStringyöntemi ve bir UriBuilderayrıştırma gibi şeyler hakkında endişelenmeden sorgu dizesi parametreleri ile çalışmaya güzel bir yol sağlar, hangi url kodlama, ...:

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"

5
Örneğimden de görebileceğiniz gibi, parametreler için değişken adları kullanabilirsiniz. Ve tam olarak yaptığı şey: burada sabit kodladığım mevcut URL'ye 2 parametre ekler, ancak mükemmel bir şekilde dinamik olabilirler.
Darin Dimitrov

1
HttpUtility.UrlEncode()Parametre değeri atarken kullanmamalı mıyız ?
UserControl

1
@UserControl, hayır, HttpUtility.ParseQueryStringyöntem , bir değer ayarladığınızda bunu sahne arkasında zaten işleyen özel bir NameValueCollection uygulaması döndürür.
Darin Dimitrov

5
Bunun System.Web: /
Pure.Krome 31.14

4
özel karakterlerin query.ToString () yöntemindeki unicode eşdeğerlerine dönüştürüleceğinden, bu yaklaşımın uluslararasılaşma ile ilgili sorunlara neden olabileceğini belirtmek gerekir.
tezromania

106

Ben sarılmış ettik Darin cevabını güzel bir şekilde yeniden kullanılabilir uzatma yöntem haline.

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

Umarım bu yardımcı olur!


55

Verilen cevapların "/ some / path /" gibi göreli Url'lerle ilgili sorunları var Bu, göreli URL'lerin neden sorunlu olabileceğine dair bir neden göremediğimden, anlaşılması oldukça zor olan Uri ve UriBuilder sınıfının bir sınırlamasıdır. sorgu manipülasyonu söz konusu olduğunda.

İşte .NET 4'te yazılmış ve test edilmiş mutlak ve göreli yollar için çalışan bir geçici çözüm:

(küçük not: bu .NET 4.5'te de çalışmalıdır, yalnızca değiştirmeniz propInfo.GetValue(values, null)gerekir 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; }
      ));
    }
  }

Ve işte davranışı test etmek için bir dizi birim test:

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

ne yazık ki bu çözüm, HttpUtility kullanılabilir görünmediğinden bulut .NET kullanan ASP.NET 5 için çalışmıyor. Ama aksi halde harika bir çözüm. Bkz. Stackoverflow.com/questions/29992848/…
diegosasw

1
"Add_to_query_string_dictionary_when_url_contains_hash_and_no_query_string_should_add_values" URL'nin domain.com/test?param1=val1¶m2=val2#div
gliljas

Kötü kaçış efektleri uri.AbsoluteUriyerine kullanmaktan daha iyi olup olmadığınızı kontrol edin uri.ToString().
Nico

2
Ayrıca: uri.AbsoluteUriuri mutlak değilse atar!
Nico

19

Microsoft.AspNetCore.WebUtilitiesNuget paketini Microsoft'tan ekleyebileceğinizi ve ardından bunu sorgu dizesine değerler eklemek için kullanabileceğinizi unutmayın:

QueryHelpers.AddQueryString(longurl, "action", "login1")
QueryHelpers.AddQueryString(longurl, new Dictionary<string, string> { { "action", "login1" }, { "attempts", "11" } });

3
ASP.NET Core 3.0'dan itibaren WebUtilities artık ASP.NET SDK'sının bir parçası olduğu için nuget paketine gerek yok.
user1069816

1
Sorun AddQueryStringşu ki, her zaman ekleyecek, zaten anahtar varsa, güncellenmeyecek, ancak yinelenen anahtarlar oluşturacak, kötü
Vencovsky

11

Aşağıdaki çözüm ASP.NET 5 (vNext) için çalışır ve parametrelerle bir URI oluşturmak için QueryHelpers sınıfını kullanır.

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

Sonuç URI'sı http://iberia.com?param1=value1&param2=value2&param3=value3


Bir Sözlük'ü sorgu anahtarları ve değerleri için depo olarak kullanmanın tek sorunu, sorgu dizelerinin farklı değerlere sahip yinelenen anahtarlara sahip olabilmesidir. Bir ASP.NET sitesine bir istek, bu bir anahtar için bir değer dizisi olarak ayrıştırdığına inanıyorum.
Seth

2

Tüm URL sorgu dizesi düzenleme sorunlarının sonu

Uri sınıfı ve diğer çözümlerle çok fazla uğraştıktan ve uğraştıktan sonra, sorunlarımı çözmek için dize genişletme yöntemlerim.

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

1
Sınıfın zaten bu amaç için var olduğu stringdüşünüldüğünde, insanların bu tür URL'leri temsil etmek için raw'ları kullanmasını önermem Uri. Bunu kullanın veya özellikler eksikse yepyeni bir soyutlama oluşturun.
julealgon

0

Bjorn'un cevabını seviyorum, ancak yöntem mevcut değilse, mevcut bir parametreyi güncellemek yerine, mevcut bir parametreyi güncellediğinden, sağladığı çözüm yanıltıcıdır. Biraz daha güvenli hale getirmek için, aşağıda uyarladım.

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

Gerçekten kodun marjinal bir düzenlemesini yaptım, ben vermedim (OP yaptı) ... fark ne olacak?

1
İf / else gerekli değilse, query[paramName] = paramValue;her durumda yapın. Var, geçersiz kılınır. Eğer mevcut değilse, anahtar oluşturulacaktır.
Richard

-4

Yeni başlayanlar için yaklaşımım çok basit:

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

    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.