รับพารามิเตอร์ url จากสตริงใน. NET


239

ฉันมีสตริงใน. NET ซึ่งจริง ๆ แล้วเป็น URL ฉันต้องการวิธีง่ายๆในการรับค่าจากพารามิเตอร์เฉพาะ

ปกติฉันจะใช้Request.Params["theThingIWant"]แต่สตริงนี้ไม่ได้มาจากคำขอ ฉันสามารถสร้างUriรายการใหม่ได้เช่น:

Uri myUri = new Uri(TheStringUrlIWantMyValueFrom);

ฉันสามารถใช้myUri.Queryเพื่อรับสตริงการสืบค้น ... แต่จากนั้นฉันก็ต้องหาวิธีแยก regexy ออกมา

ฉันขาดอะไรบางอย่างที่เห็นได้ชัดหรือไม่มีวิธีที่จะทำให้การสร้าง regex ของบางประเภท ฯลฯ มีปัญหาหรือไม่?

คำตอบ:


494

ใช้แบบคงที่ParseQueryStringวิธีการของชั้นเรียนที่ผลตอบแทนSystem.Web.HttpUtilityNameValueCollection

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

ตรวจสอบเอกสารที่http://msdn.microsoft.com/en-us/library/ms150046.aspx


14
ดูเหมือนจะไม่พบพารามิเตอร์แรก เช่นการแยกวิเคราะห์ " google.com/… " ไม่พบพารามิเตอร์ q
Andrew Shepherd

@ แอนดรูว์ฉันยืนยัน มันแปลก (บั๊ก?) คุณยังคงใช้HttpUtility.ParseQueryString(myUri.Query).Get(0)แม้ว่าและมันจะแยกพารามิเตอร์แรก `
Mariusz Pawelski

เครื่องมือ. NET ใด ๆ เพื่อสร้าง URL แบบสอบถามแบบใช้พารามิเตอร์
Shimmy Weitzhandler

6
คุณไม่สามารถแยกวิเคราะห์ URL แบบเต็มด้วยHttpUtility.ParseQueryString(string)! ตามที่ชื่อบอกไว้มันจะแยกวิเคราะห์ Query Strings ไม่ใช่ URL ที่มีพารามิเตอร์ข้อความค้นหา หากคุณต้องการที่จะทำอันดับแรกคุณต้องแยกออกได้โดยการ?เช่นนี้Url.Split('?')และได้รับการใช้องค์ประกอบสุดท้าย (ขึ้นอยู่กับสถานการณ์และสิ่งที่คุณต้องการ) [0]หรือ LINQ ของ/Last() LastOrDefault()
Kosiek

1
เมื่อทำการทดลองด้วยตัวเองลายเซ็นจะเปลี่ยนเป็น: HttpUtility.ParseQueryString (uri.Query) .GetValues ​​("param1"). First ()
สมาชิกวุฒิสภา

48

นี่อาจเป็นสิ่งที่คุณต้องการ

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

HttpUtility.ParseQueryString()นี่เป็นอีกทางเลือกหนึ่งถ้าด้วยเหตุผลใดก็ตามที่คุณไม่สามารถหรือไม่ต้องการที่จะใช้

สิ่งนี้ถูกสร้างขึ้นให้มีความทนทานต่อสตริงข้อความค้นหาที่ "ผิดรูปแบบ" เช่นhttp://test/test.html?empty=กลายเป็นพารามิเตอร์ที่มีค่าว่าง ผู้เรียกสามารถตรวจสอบพารามิเตอร์ได้ถ้าต้องการ

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

ทดสอบ

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

มีประโยชน์สำหรับโครงการ Xamarin ที่ HttpUtility ไม่พร้อมใช้งาน
Artemious

12

@Andrew และ @CZFox

ฉันมีข้อผิดพลาดเดียวกันและพบว่าสาเหตุที่เป็นพารามิเตอร์นั้นอันที่จริงแล้ว: http://www.example.com?param1และไม่ใช่param1สิ่งที่ใครคาดหวัง

โดยลบตัวอักษรทั้งหมดก่อนและรวมถึงเครื่องหมายคำถามช่วยแก้ไขปัญหา ดังนั้นในสาระสำคัญHttpUtility.ParseQueryStringฟังก์ชั่นจะต้องใช้พารามิเตอร์สตริงแบบสอบถามที่ถูกต้องที่มีตัวอักษรเพียงหลังเครื่องหมายคำถามเช่นเดียวกับใน:

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

วิธีแก้ปัญหาของฉัน:

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" );`

เมื่อ URI ได้รับการยกตัวอย่างฉันได้รับข้อผิดพลาด "URI ไม่ถูกต้อง: ไม่สามารถระบุรูปแบบของ URI ได้" ฉันไม่คิดว่าวิธีนี้จะทำงานได้ตามที่ต้องการ
พอลแมตทิวส์

@ PaulMatthews คุณถูกต้อง ในช่วงเวลาของการแก้ปัญหาที่กำหนดนี้ฉันใช้. NET Framework 2.0 ที่เก่ากว่า เพื่อยืนยันว่าข้อความของคุณฉันได้คัดลอกและวางโซลูชันนี้ลงใน LINQPad v2 โดย Joseph Albahara และได้รับข้อผิดพลาดเดียวกับที่คุณพูดถึง
Mo Gauvin

@PaulMatthews หากต้องการแก้ไขให้ลบบรรทัดที่อ่าน Uri myUri = Uri ใหม่ (RawUrl); และเพียงส่งผ่าน RawUrl ไปยังคำสั่งสุดท้ายใน: string param1 = HttpUtility.ParseQueryString (RawUrl) .Get ("param2");
Mo Gauvin

ใช่ความจริงที่ว่ามันแยกวิเคราะห์เฉพาะส่วนสตริงแบบสอบถามอยู่ในชื่อและในเอกสารประกอบ มันไม่ใช่ข้อผิดพลาด ฉันไม่แน่ใจด้วยซ้ำว่าจะทำให้ชัดเจนขึ้นได้อย่างไร ParseQueryStringวิเคราะห์คำสตริงการสืบค้น
PandaWood

12

ดูเหมือนว่าคุณควรวนค่าmyUri.Queryและแยกออกจากที่นั่น

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

ฉันจะไม่ใช้รหัสนี้หากไม่ได้ทดสอบกับ URL ที่มีรูปแบบไม่ถูกต้อง มันอาจจะทำลายบางส่วน / ทั้งหมดเหล่านี้:

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

4

คุณสามารถใช้วิธีแก้ปัญหาต่อไปนี้เพื่อทำงานกับพารามิเตอร์แรกด้วย:

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

2

ใช้ .NET สะท้อนเพื่อดูวิธีการFillFromString System.Web.HttpValueCollectionที่ให้รหัสที่ ASP.NET ใช้เติมRequest.QueryStringคอลเลกชัน


1

หรือหากคุณไม่ทราบ URL (เพื่อหลีกเลี่ยงการเข้ารหัส) ให้ใช้ AbsoluteUri

ตัวอย่าง ...

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

หากคุณต้องการรับ QueryString บนหน้าเริ่มต้นหน้าเริ่มต้นหมายถึง URL หน้าปัจจุบันของคุณ คุณสามารถลองรหัสนี้:

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

0

จริงๆแล้วมันง่ายมากและใช้งานได้สำหรับฉัน :)

        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

สำหรับทุกคนที่ต้องการวนลูปผ่านสตริงการสืบค้นทั้งหมดจากสตริง

        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
        }


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.