Dapatkan parameter url dari string di .NET


239

Saya punya string di .NET yang sebenarnya adalah url. Saya ingin cara mudah untuk mendapatkan nilai dari parameter tertentu.

Biasanya, saya hanya menggunakan Request.Params["theThingIWant"], tetapi string ini bukan dari permintaan. Saya dapat membuat Uriitem baru seperti ini:

Uri myUri = new Uri(TheStringUrlIWantMyValueFrom);

Saya dapat menggunakan myUri.Queryuntuk mendapatkan string kueri ... tapi kemudian saya harus mencari cara untuk memisahkannya.

Apakah saya kehilangan sesuatu yang jelas, atau apakah tidak ada cara yang dibangun untuk melakukan ini singkat menciptakan semacam regex, dll?

Jawaban:


494

Gunakan ParseQueryStringmetode statis System.Web.HttpUtilitykelas yang kembali NameValueCollection.

Uri myUri = new Uri("http://www.example.com?param1=good&param2=bad");
string param1 = HttpUtility.ParseQueryString(myUri.Query).Get("param1");

Periksa dokumentasi di http://msdn.microsoft.com/en-us/library/ms150046.aspx


14
Tampaknya ini tidak mendeteksi parameter pertama. misal parsing " google.com/... " tidak mendeteksi parameter q
Andrew Shepherd

@Andrew saya konfirmasi. Aneh (bug?). Anda masih dapat menggunakan HttpUtility.ParseQueryString(myUri.Query).Get(0)dan akan mengekstrak parameter pertama. `
Mariusz Pawelski

Adakah alat .NET untuk membangun url kueri parameter?
Shimmy Weitzhandler

6
Anda tidak dapat menguraikan URL kueri lengkap dengan HttpUtility.ParseQueryString(string)! Seperti namanya, ini untuk mem-parsing String Kueri, bukan URL dengan parameter kueri. Jika Anda ingin melakukannya, Anda harus membaginya terlebih dahulu dengan ?seperti ini: Url.Split('?')dan mendapatkan elemen terakhir menggunakan (tergantung pada situasi dan apa yang Anda butuhkan) [0]atau LINQ's Last()/ LastOrDefault().
Kosiek

1
Ketika mencoba ini sendiri, tanda tangan tampaknya telah berubah menjadi ini: HttpUtility.ParseQueryString (uri.Query) .Dapatkan Nilai ("param1"). First ()
Senator

48

Ini mungkin yang Anda inginkan

var uri = new Uri("http://domain.test/Default.aspx?var1=true&var2=test&var3=3");
var query = HttpUtility.ParseQueryString(uri.Query);

var var2 = query.Get("var2");

34

Berikut alternatif lain jika, karena alasan apa pun, Anda tidak dapat atau tidak ingin menggunakannya HttpUtility.ParseQueryString().

Ini dibuat agar agak toleran terhadap string kueri "salah bentuk", yaitu http://test/test.html?empty=menjadi parameter dengan nilai kosong. Penelepon dapat memverifikasi parameter jika diperlukan.

public static class UriHelper
{
    public static Dictionary<string, string> DecodeQueryParameters(this Uri uri)
    {
        if (uri == null)
            throw new ArgumentNullException("uri");

        if (uri.Query.Length == 0)
            return new Dictionary<string, string>();

        return uri.Query.TrimStart('?')
                        .Split(new[] { '&', ';' }, StringSplitOptions.RemoveEmptyEntries)
                        .Select(parameter => parameter.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries))
                        .GroupBy(parts => parts[0],
                                 parts => parts.Length > 2 ? string.Join("=", parts, 1, parts.Length - 1) : (parts.Length > 1 ? parts[1] : ""))
                        .ToDictionary(grouping => grouping.Key,
                                      grouping => string.Join(",", grouping));
    }
}

Uji

[TestClass]
public class UriHelperTest
{
    [TestMethod]
    public void DecodeQueryParameters()
    {
        DecodeQueryParametersTest("http://test/test.html", new Dictionary<string, string>());
        DecodeQueryParametersTest("http://test/test.html?", new Dictionary<string, string>());
        DecodeQueryParametersTest("http://test/test.html?key=bla/blub.xml", new Dictionary<string, string> { { "key", "bla/blub.xml" } });
        DecodeQueryParametersTest("http://test/test.html?eins=1&zwei=2", new Dictionary<string, string> { { "eins", "1" }, { "zwei", "2" } });
        DecodeQueryParametersTest("http://test/test.html?empty", new Dictionary<string, string> { { "empty", "" } });
        DecodeQueryParametersTest("http://test/test.html?empty=", new Dictionary<string, string> { { "empty", "" } });
        DecodeQueryParametersTest("http://test/test.html?key=1&", new Dictionary<string, string> { { "key", "1" } });
        DecodeQueryParametersTest("http://test/test.html?key=value?&b=c", new Dictionary<string, string> { { "key", "value?" }, { "b", "c" } });
        DecodeQueryParametersTest("http://test/test.html?key=value=what", new Dictionary<string, string> { { "key", "value=what" } });
        DecodeQueryParametersTest("http://www.google.com/search?q=energy+edge&rls=com.microsoft:en-au&ie=UTF-8&oe=UTF-8&startIndex=&startPage=1%22",
            new Dictionary<string, string>
            {
                { "q", "energy+edge" },
                { "rls", "com.microsoft:en-au" },
                { "ie", "UTF-8" },
                { "oe", "UTF-8" },
                { "startIndex", "" },
                { "startPage", "1%22" },
            });
        DecodeQueryParametersTest("http://test/test.html?key=value;key=anotherValue", new Dictionary<string, string> { { "key", "value,anotherValue" } });
    }

    private static void DecodeQueryParametersTest(string uri, Dictionary<string, string> expected)
    {
        Dictionary<string, string> parameters = new Uri(uri).DecodeQueryParameters();
        Assert.AreEqual(expected.Count, parameters.Count, "Wrong parameter count. Uri: {0}", uri);
        foreach (var key in expected.Keys)
        {
            Assert.IsTrue(parameters.ContainsKey(key), "Missing parameter key {0}. Uri: {1}", key, uri);
            Assert.AreEqual(expected[key], parameters[key], "Wrong parameter value for {0}. Uri: {1}", parameters[key], uri);
        }
    }
}

bermanfaat untuk proyek Xamarin, di mana HttpUtility tidak tersedia
Artemious

12

@Andrew dan @CZFox

Saya memiliki bug yang sama dan menemukan penyebabnya menjadi parameter satu sebenarnya: http://www.example.com?param1dan bukan param1yang diharapkan.

Dengan menghapus semua karakter sebelum dan termasuk tanda tanya memperbaiki masalah ini. Jadi pada dasarnya HttpUtility.ParseQueryStringfungsi ini hanya memerlukan parameter string kueri yang valid yang hanya berisi karakter setelah tanda tanya seperti pada:

HttpUtility.ParseQueryString ( "param1=good&param2=bad" )

Solusi saya:

string RawUrl = "http://www.example.com?param1=good&param2=bad";
int index = RawUrl.IndexOf ( "?" );
if ( index > 0 )
    RawUrl = RawUrl.Substring ( index ).Remove ( 0, 1 );

Uri myUri = new Uri( RawUrl, UriKind.RelativeOrAbsolute);
string param1 = HttpUtility.ParseQueryString( myUri.Query ).Get( "param1" );`

Ketika URI dipakai, saya mendapatkan kesalahan "URI tidak valid: Format URI tidak dapat ditentukan." Saya tidak berpikir solusi ini berfungsi sebagaimana dimaksud.
Paul Matthews

@PaulMatthews, Anda benar. Pada saat solusi yang diberikan ini, saya menggunakan .net framework 2.0 yang lebih lama. Untuk mengonfirmasi, pernyataan Anda, saya menyalin dan menempelkan solusi ini ke LINQPad v2 oleh Joseph Albahara dan menerima kesalahan yang sama seperti yang Anda sebutkan.
Mo Gauvin

@PaulMatthews, Untuk memperbaikinya, hapus baris yang bertuliskan Uri myUri = new Uri (RawUrl); dan hanya meneruskan RawUrl ke pernyataan terakhir seperti di: string param1 = HttpUtility.ParseQueryString (RawUrl) .Dapatkan ("param2");
Mo Gauvin

Ya, fakta bahwa ia hanya mem-parsing bagian string kueri dalam nama dan dalam dokumentasi. Itu bukan bug. Saya bahkan tidak yakin bagaimana mereka bisa membuatnya lebih jelas. ParseQueryStringmem-parsing string kueri.
PandaWood

12

Sepertinya Anda harus mengulang nilai myUri.Querydan parsing dari sana.

 string desiredValue;
 foreach(string item in myUri.Query.Split('&'))
 {
     string[] parts = item.Replace("?", "").Split('=');
     if(parts[0] == "desiredKey")
     {
         desiredValue = parts[1];
         break;
     }
 }

Namun saya tidak akan menggunakan kode ini tanpa mengujinya pada sekelompok URL yang rusak. Mungkin rusak pada beberapa / semua ini:

  • hello.html?
  • hello.html?valuelesskey
  • hello.html?key=value=hi
  • hello.html?hi=value?&b=c
  • dll

4

Anda dapat menggunakan solusi berikut ini untuk berfungsi dengan parameter pertama juga:

var param1 =
    HttpUtility.ParseQueryString(url.Substring(
        new []{0, url.IndexOf('?')}.Max()
    )).Get("param1");

2

Gunakan .NET Reflector untuk melihat FillFromStringmetode System.Web.HttpValueCollection. Itu memberi Anda kode yang digunakan ASP.NET untuk mengisi Request.QueryStringkoleksi.


1

Atau jika Anda tidak tahu URL (untuk menghindari hardcoding, gunakan AbsoluteUri

Contoh ...

        //get the full URL
        Uri myUri = new Uri(Request.Url.AbsoluteUri);
        //get any parameters
        string strStatus = HttpUtility.ParseQueryString(myUri.Query).Get("status");
        string strMsg = HttpUtility.ParseQueryString(myUri.Query).Get("message");
        switch (strStatus.ToUpper())
        {
            case "OK":
                webMessageBox.Show("EMAILS SENT!");
                break;
            case "ER":
                webMessageBox.Show("EMAILS SENT, BUT ... " + strMsg);
                break;
        }

0

jika Anda ingin mendapatkan QueryString Anda pada halaman Default. Halaman default berarti url halaman Anda saat ini. Anda dapat mencoba kode ini:

string paramIl = HttpUtility.ParseQueryString(this.ClientQueryString).Get("city");

0

Ini sebenarnya sangat sederhana, dan itu berhasil untuk saya :)

        if (id == "DK")
        {
            string longurl = "selectServer.aspx?country=";
            var uriBuilder = new UriBuilder(longurl);
            var query = HttpUtility.ParseQueryString(uriBuilder.Query);
            query["country"] = "DK";

            uriBuilder.Query = query.ToString();
            longurl = uriBuilder.ToString();
        } 

0

Bagi siapa saja yang ingin mengulang semua string kueri dari sebuah string

        foreach (var item in new Uri(urlString).Query.TrimStart('?').Split('&'))
        {
            var subStrings = item.Split('=');

            var key = subStrings[0];
            var value = subStrings[1];

            // do something with values
        }


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.