Cara mengurai string kueri ke dalam NameValueCollection di .NET


186

Saya ingin mengurai string seperti p1=6&p2=7&p3=8menjadi NameValueCollection.

Apa cara paling elegan untuk melakukan ini ketika Anda tidak memiliki akses ke Page.Requestobjek?

Jawaban:


356

Ada utilitas .NET bawaan untuk ini: HttpUtility.ParseQueryString

// C#
NameValueCollection qscoll = HttpUtility.ParseQueryString(querystring);
' VB.NET
Dim qscoll As NameValueCollection = HttpUtility.ParseQueryString(querystring)

Anda mungkin perlu mengganti querystringdengan new Uri(fullUrl).Query.


26
Omar, itu tidak bekerja untuk saya di ASP.NET 4, itu mengembalikan kunci " stackoverflow.com?para " bukan "para". Jadi saya menggunakan HttpUtility.ParseQueryString (Uri baru (fullUrl) .Query) yang berfungsi dengan baik untuk saya.
Michael

2
qscoll ["p1"], qscoll ["p2"] dan qscoll ["p3"]
SMUsamaShah

5
ParseQueryString adalah ide yang sangat buruk untuk digunakan dalam aplikasi desktop, karena itu tidak termasuk dalam Profil Klien; mengapa menginstal 100 M perpustakaan tambahan di komputer klien untuk hanya menggunakan satu metode sederhana? Namun, sepertinya Microsoft tidak memiliki ide yang lebih baik. Satu-satunya cara adalah menerapkan metode sendiri atau menggunakan implementasi open source.
Vitalii

2
VASoftOnline: Dalam hal ini Anda dapat menggunakan implementasi Mono dari ParseQueryString: github.com/mono/mono/blob/master/mcs/class/System.Web/… lisensi untuk itu adalah MIT X11: github.com/mono/mono / blob / master / LICENSE
sw.

3
HttpUtility.ParseQueryStringakan menjadi rekomendasi saya kecuali bahwa dalam kasus HttpUtility.ParseQueryString("&X=1&X=2&X=3")hasilnya adalah ....X=1,2,3...Memiliki beberapa params dengan nama yang sama tidak umum tetapi diperlukan untuk mendukung parameter pengontrol seperti int [], IEnumerable <int> dll (param tersebut dapat digunakan untuk mendukung beberapa kotak centang) lihat "Beberapa kemunculan variabel string kueri yang sama dikonsolidasikan dalam satu entri" sesuai situs MS . Versi buatan tangan dari metode ini mungkin satu-satunya pilihan Anda
dunxz

43

HttpUtility.ParseQueryString akan bekerja selama Anda berada di aplikasi web atau tidak keberatan termasuk ketergantungan pada System.Web. Cara lain untuk melakukan ini adalah:

NameValueCollection queryParameters = new NameValueCollection();
string[] querySegments = queryString.Split('&');
foreach(string segment in querySegments)
{
   string[] parts = segment.Split('=');
   if (parts.Length > 0)
   {
      string key = parts[0].Trim(new char[] { '?', ' ' });
      string val = parts[1].Trim();

      queryParameters.Add(key, val);
   }
}

5
Anda harus memeriksa apakah bagian. Panjang> 1, untuk memastikan Anda dapat memanggil bagian [1]
Alexandru Pupsa

2
Bagaimana jika tidak ada nilai? misal string kueri dapat terlihat seperti ?foo=1&bar. HttpUtilityakan menguraikannya sebagai{ key = null, value = "bar" }
Thomas Levesque

Ini bagus dibandingkan dengan HttpUtility.ParseQueryString karena tidak memecahkan kode nilai (jadi nilai base64 yang dikodekan dipertahankan)
CRice

1
Sebenarnya, Anda masih perlu mengizinkan nilai '=' misalnya & kode = A0SYw34Hj / m ++ lH0s7r0l / yg6GWdymzSCbI2zOn3V4o = akan menghapus karakter '=' terakhir dihapus. Saya menulis ulang bagian dari kode Anda untuk mendapatkan indeks pertama '=' dan substring kunci dan nilai untuk memperbaikinya (alih-alih menggunakan split).
CRice

28

Banyak jawaban yang memberikan contoh khusus karena ketergantungan jawaban yang diterima pada System.Web . Dari paket NuGet Microsoft.AspNet.WebApi.Client ada UriExtensions.ParseQueryString , metode yang juga dapat digunakan:

var uri = new Uri("https://stackoverflow.com/a/22167748?p1=6&p2=7&p3=8");
NameValueCollection query = uri.ParseQueryString();

Jadi, jika Anda ingin menghindari ketergantungan System.Web dan tidak ingin menjalankannya sendiri, ini adalah opsi yang baik.


3
Fungsi yang sama ada sebagai ekstensi dalam namespace System.Net.Http (lihat jawaban saya di bawah), tidak perlu untuk seluruh dependensi lain ...
jvenema

@jvenema Dari mana Anda menambahkan dependensi System.Net.Http.Formatting, saya percaya itu hanya disediakan dengan menambahkan paket NuGet Microsoft.AspNet.WebApi.Client.
James Skimming

19

Saya ingin menghapus ketergantungan pada System.Web sehingga saya dapat mengurai string kueri penyebaran ClickOnce, sementara prasyaratnya terbatas pada "Subset Kerangka Kerja Khusus Klien".

Saya menyukai jawaban rp. Saya menambahkan beberapa logika tambahan.

public static NameValueCollection ParseQueryString(string s)
    {
        NameValueCollection nvc = new NameValueCollection();

        // remove anything other than query string from url
        if(s.Contains("?"))
        {
            s = s.Substring(s.IndexOf('?') + 1);
        }

        foreach (string vp in Regex.Split(s, "&"))
        {
            string[] singlePair = Regex.Split(vp, "=");
            if (singlePair.Length == 2)
            {
                nvc.Add(singlePair[0], singlePair[1]);
            }
            else
            {
                // only one key with no value specified in query string
                nvc.Add(singlePair[0], string.Empty);
            }
        }

        return nvc;
    }

ini sangat membantu untuk windows phone, Anda hanya perlu mengganti "NameValueCollection" dengan "SortedDictionnary <string, string>"
Mike Bryant

4
Hati-hati saat mengganti NameValueCollection untuk Kamus - keduanya tidak sama! String kueri mendukung beberapa kunci dengan nilai yang sama, dan begitu pula NameValueCollection.
Matt DeKrey

7

Saya membutuhkan fungsi yang sedikit lebih fleksibel daripada apa yang sudah disediakan saat bekerja dengan permintaan OLSC.

  • Nilai dapat berisi beberapa tanda sama dengan
  • Dekode karakter yang disandikan dalam nama dan nilai
  • Mampu berjalan pada Kerangka Klien
  • Mampu berjalan pada Kerangka Seluler.

Ini solusinya:

Public Shared Function ParseQueryString(ByVal uri As Uri) As System.Collections.Specialized.NameValueCollection
    Dim result = New System.Collections.Specialized.NameValueCollection(4)
    Dim query = uri.Query
    If Not String.IsNullOrEmpty(query) Then
        Dim pairs = query.Substring(1).Split("&"c)
        For Each pair In pairs
            Dim parts = pair.Split({"="c}, 2)

            Dim name = System.Uri.UnescapeDataString(parts(0))
            Dim value = If(parts.Length = 1, String.Empty,
                System.Uri.UnescapeDataString(parts(1)))

            result.Add(name, value)
        Next
    End If
    Return result
End Function

Mungkin bukan ide yang buruk <Extension()>untuk memperbaikinya juga untuk menambah kemampuan Uri itu sendiri.


7

Untuk melakukannya tanpa System.Web, tanpa menulis sendiri, dan tanpa paket NuGet tambahan:

  1. Tambahkan referensi ke System.Net.Http.Formatting
  2. Menambahkan using System.Net.Http;
  3. Gunakan kode ini:

    new Uri(uri).ParseQueryString()

https://msdn.microsoft.com/en-us/library/system.net.http.uriextensions(v=vs.118).aspx


3
Dari mana Anda menambahkan dependensi System.Net.Http.Formatting, saya yakin itu hanya disediakan dengan menambahkan paket NuGet Microsoft.AspNet.WebApi.Client.
James Skimming

Hah, salahku. Saya kira itu datang dengan kerangka kerja MVC yang diinstal secara otomatis, jadi saya tidak perlu menambahkan paket add'l (File Program (x86) \ Microsoft ASP.NET \ ASP.NET MVC 4 \ Assemblies \ System.Net. Http.Formatting.dll)
jvenema

System.Net.Formatting EXTENSION VS2019 adalah daftar atau tab terpisah dari dari referensi kerangka kerja tradisional
Sql Surfer

3

Jika Anda ingin menghindari ketergantungan pada System.Web yang diperlukan untuk menggunakan HttpUtility.ParseQueryString , Anda bisa menggunakan Urimetode ekstensi yang ParseQueryStringditemukan diSystem.Net.Http .

Pastikan untuk menambahkan referensi (jika Anda belum) ke System.Net.Http dalam proyek Anda.

Perhatikan bahwa Anda harus mengonversi badan respons ke valid Uriagar ParseQueryString(in System.Net.Http) berfungsi.

string body = "value1=randomvalue1&value2=randomValue2";

// "http://localhost/query?" is added to the string "body" in order to create a valid Uri.
string urlBody = "http://localhost/query?" + body;
NameValueCollection coll = new Uri(urlBody).ParseQueryString();

System.Net.Formatting EXTENSION VS2019 menempatkan referensi ekstensi terpisah dari referensi kerangka kerja tradisional.
Sql Surfer

2
    private void button1_Click( object sender, EventArgs e )
    {
        string s = @"p1=6&p2=7&p3=8";
        NameValueCollection nvc = new NameValueCollection();

        foreach ( string vp in Regex.Split( s, "&" ) )
        {
            string[] singlePair = Regex.Split( vp, "=" );
            if ( singlePair.Length == 2 )
            {
                nvc.Add( singlePair[ 0 ], singlePair[ 1 ] );    
            }    
        }
    }

5
titik koma juga diperbolehkan sebagai pemisah parameter dalam http, lebih baik tidak menemukan kembali roda
Matthew Lock

2

Saya baru menyadari bahwa Web API Client memiliki ParseQueryStringmetode ekstensi yang berfungsi pada Uridan mengembalikan HttpValueCollection:

var parameters = uri.ParseQueryString();
string foo = parameters["foo"];

1

Cukup akses Request.QueryString. AllKeys disebut sebagai jawaban lain hanya memberi Anda berbagai kunci.


1

HttpUtility.ParseQueryString(Request.Url.Query)return adalah HttpValueCollection(kelas internal). Itu mewarisi dari NameValueCollection.

    var qs = HttpUtility.ParseQueryString(Request.Url.Query);
    qs.Remove("foo"); 

    string url = "~/Default.aspx"; 
    if (qs.Count > 0)
       url = url + "?" + qs.ToString();

    Response.Redirect(url); 

1

Jika Anda tidak menginginkan ketergantungan System.Web, cukup tempel kode sumber ini dari kelas HttpUtility.

Saya baru saja mencabut ini bersama-sama dari kode sumber Mono . Ini berisi HttpUtility dan semua dependensinya (seperti IHtmlString, Helpers, HttpEncoder, HttpQSCollection).

Lalu gunakanHttpUtility.ParseQueryString .

https://gist.github.com/bjorn-ali-goransson/b04a7c44808bb2de8cca3fc9a3762f9c


1

Karena semua orang sepertinya menempelkan solusinya .. ini milik saya :-) Saya membutuhkan ini dari dalam perpustakaan kelas tanpa System.Web mengambil parameter id dari hyperlink yang tersimpan.

Saya pikir saya akan berbagi karena saya menemukan solusi ini lebih cepat dan lebih tampan.

public static class Statics
    public static Dictionary<string, string> QueryParse(string url)
    {
        Dictionary<string, string> qDict = new Dictionary<string, string>();
        foreach (string qPair in url.Substring(url.IndexOf('?') + 1).Split('&'))
        {
            string[] qVal = qPair.Split('=');
            qDict.Add(qVal[0], Uri.UnescapeDataString(qVal[1]));
        }
        return qDict;
    }

    public static string QueryGet(string url, string param)
    {
        var qDict = QueryParse(url);
        return qDict[param];
    }
}

Pemakaian:

Statics.QueryGet(url, "id")

1
Hanya satu masalah dengan metode ini: string kueri dapat memiliki lebih dari satu nilai untuk parameter yang diberikan. Dalam hal ini, metode Anda akan melempar kesalahan kunci duplikat.
Thomas Levesque

ya, setidaknya gunakan NameValueCollection, querystrings dengan kunci duplikat sangat legal.
Chad Grant

Juga, kamus Anda peka terhadap huruf besar-kecil, jadi X = 1 dan x = 1 akan menjadi kunci yang berbeda. Perlu Kamus baru <string, string> (StringComparer.OrdinalIgnoreCase);
Chad Grant

0

Tekan Request.QueryString.Keys untuk NameValueCollection dari semua parameter string kueri.


0

Untuk mendapatkan semua nilai Querystring coba ini:

    Dim qscoll As NameValueCollection = HttpUtility.ParseQueryString(querystring)

Dim sb As New StringBuilder("<br />")
For Each s As String In qscoll.AllKeys

  Response.Write(s & " - " & qscoll(s) & "<br />")

Next s

0
        var q = Request.QueryString;
        NameValueCollection qscoll = HttpUtility.ParseQueryString(q.ToString());

0
let search = window.location.search;

console.log(search);

let qString = search.substring(1);

while(qString.indexOf("+") !== -1)

   qString  = qString.replace("+", "");

let qArray = qString.split("&");

let values = [];

for(let i = 0; i < qArray.length; i++){
   let pos = qArray[i].search("=");
   let keyVal = qArray[i].substring(0, pos);
   let dataVal = qArray[i].substring(pos + 1);
   dataVal = decodeURIComponent(dataVal);
   values[keyVal] = dataVal;
}

-1

Saya menerjemahkan ke versi C # josh-brown di VB

private System.Collections.Specialized.NameValueCollection ParseQueryString(Uri uri)
{
    var result = new System.Collections.Specialized.NameValueCollection(4);
    var query = uri.Query;
    if (!String.IsNullOrEmpty(query))
    {
        var pairs = query.Substring(1).Split("&".ToCharArray());
        foreach (var pair in pairs)
        {
            var parts = pair.Split("=".ToCharArray(), 2);
            var name = System.Uri.UnescapeDataString(parts[0]);
            var value = (parts.Length == 1) ? String.Empty : System.Uri.UnescapeDataString(parts[1]);
            result.Add(name, value);
        }
    }
    return result;
}

-2

Ini kode saya, saya pikir ini sangat berguna:

public String GetQueryString(string ItemToRemoveOrInsert = null, string InsertValue = null )
{
    System.Collections.Specialized.NameValueCollection filtered = new System.Collections.Specialized.NameValueCollection(Request.QueryString);
    if (ItemToRemoveOrInsert != null)
    {
        filtered.Remove(ItemToRemoveOrInsert);
        if (!string.IsNullOrWhiteSpace(InsertValue))
        {
            filtered.Add(ItemToRemoveOrInsert, InsertValue);
        }
    }

    string StrQr = string.Join("&", filtered.AllKeys.Select(key => key + "=" + filtered[key]).ToArray());
    if (!string.IsNullOrWhiteSpace(StrQr)){
        StrQr="?" + StrQr;
    }

    return StrQr;
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.