Nhận tham số url từ một chuỗi trong .NET


239

Tôi đã có một chuỗi trong .NET thực sự là một url. Tôi muốn một cách dễ dàng để có được giá trị từ một tham số cụ thể.

Thông thường, tôi chỉ sử dụng Request.Params["theThingIWant"], nhưng chuỗi này không xuất phát từ yêu cầu. Tôi có thể tạo một Urimục mới như vậy:

Uri myUri = new Uri(TheStringUrlIWantMyValueFrom);

Tôi có thể sử dụng myUri.Queryđể có được chuỗi truy vấn ... nhưng sau đó tôi rõ ràng phải tìm một số cách khó hiểu để tách nó ra.

Có phải tôi đang thiếu một cái gì đó rõ ràng, hoặc không có cách nào để tạo ra một regex của một loại nào đó, v.v.?

Câu trả lời:


494

Sử dụng ParseQueryStringphương thức tĩnh của System.Web.HttpUtilitylớp trả về NameValueCollection.

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

Kiểm tra tài liệu tại http://msdn.microsoft.com/en-us/l Library / ms150046.aspx


14
Điều này dường như không phát hiện ra tham số đầu tiên. ví dụ: phân tích cú pháp " google.com/, " không phát hiện ra tham số q
Andrew Shepherd

@Andrew tôi xác nhận. Thật lạ (lỗi?). Bạn coul vẫn sử dụng HttpUtility.ParseQueryString(myUri.Query).Get(0)mặc dù và nó sẽ trích xuất tham số đầu tiên. `
Mariusz Pawelski

Bất kỳ công cụ .NET để xây dựng một url truy vấn tham số?
Shimmy Weitzhandler

6
Bạn không thể phân tích cú pháp URL đầy đủ với HttpUtility.ParseQueryString(string)! Như tên của nó, nó phân tích các Chuỗi truy vấn, không phải các URL có tham số truy vấn. Nếu bạn muốn làm điều đó, trước tiên bạn phải phân chia nó ?như thế này: Url.Split('?')và lấy phần tử cuối cùng bằng cách sử dụng (tùy thuộc vào tình huống và những gì bạn cần) [0]hoặc LINQ's Last()/ LastOrDefault().
Kosiek

1
Khi trialling này bản thân mình, chữ ký dường như đã thay đổi như thế này: HttpUtility.ParseQueryString (uri.Query) .GetValues ( "param1") đầu tiên ().
Các Thượng nghị sĩ

48

Đây có lẽ là những gì bạn muốn

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

Đây là một lựa chọn khác nếu, vì bất kỳ lý do gì, bạn không thể hoặc không muốn sử dụng HttpUtility.ParseQueryString().

Điều này được xây dựng để có thể khoan dung hơn với các chuỗi truy vấn "không đúng định dạng", tức là http://test/test.html?empty=trở thành một tham số có giá trị trống. Người gọi có thể xác minh các tham số nếu cần.

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

Kiểm tra

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

hữu ích cho dự án Xamarin, nơi không có
httpUtility

12

@Andrew và @CZFox

Tôi đã có cùng một lỗi và tìm ra nguyên nhân là tham số đó thực tế là: http://www.example.com?param1param1đó không phải là điều người ta mong đợi.

Bằng cách loại bỏ tất cả các ký tự trước và bao gồm cả dấu hỏi sẽ khắc phục vấn đề này. Vì vậy, về bản chất, HttpUtility.ParseQueryStringhàm chỉ yêu cầu một tham số chuỗi truy vấn hợp lệ chỉ chứa các ký tự sau dấu chấm hỏi như trong:

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

Cách giải quyết của tôi:

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

Khi URI được khởi tạo, tôi nhận được lỗi "URI không hợp lệ: Không thể xác định định dạng của URI." Tôi không nghĩ giải pháp này hoạt động như dự định.
Paul Matthews

@PaulMatthews, bạn đúng rồi. Tại thời điểm đưa ra giải pháp này, tôi đang sử dụng .net framework 2.0 cũ hơn. Để xác nhận, tuyên bố của bạn, tôi đã sao chép và dán giải pháp này vào LINQPad v2 bởi Joseph Albahara và nhận được lỗi tương tự như bạn đã đề cập.
Mo Gauvin

@PaulMatthews, Để khắc phục, hãy xóa dòng đọc Uri myUri = new Uri (RawUrl); và chỉ đơn thuần chuyển RawUrl đến câu lệnh cuối cùng như trong: string param1 = HttpUtility.PudeQueryString (RawUrl) .Get ("param2");
Mo Gauvin

Vâng, thực tế là nó chỉ phân tích phần chuỗi truy vấn nằm trong tên và trong tài liệu. Đó không phải là một lỗi. Tôi thậm chí không chắc làm thế nào họ có thể làm cho nó rõ ràng hơn. ParseQueryStringphân tích chuỗi truy vấn.
PandaWood

12

Có vẻ như bạn nên lặp lại các giá trị myUri.Queryvà phân tích nó từ đó.

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

Tuy nhiên, tôi sẽ không sử dụng mã này mà không kiểm tra mã này trên một loạt các URL không đúng định dạng. Nó có thể phá vỡ một số / tất cả trong số này:

  • hello.html?
  • hello.html?valuelesskey
  • hello.html?key=value=hi
  • hello.html?hi=value?&b=c
  • Vân vân

4

Bạn cũng có thể sử dụng cách giải quyết sau để nó hoạt động với tham số đầu tiên:

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

2

Sử dụng .NET Reflector để xem FillFromStringphương thức của System.Web.HttpValueCollection. Điều đó cung cấp cho bạn mã mà ASP.NET đang sử dụng để điền vào Request.QueryStringbộ sưu tập.


1

Hoặc nếu bạn không biết URL (để tránh mã hóa cứng, hãy sử dụng AbsoluteUri

Thí dụ ...

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

nếu bạn muốn nhận QueryString trên trang Mặc định. Trang lỗi có nghĩa là url trang hiện tại của bạn. bạn có thể thử mã này:

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

0

Điều này thực sự rất đơn giản, và nó đã làm việc cho tôi :)

        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

Đối với bất kỳ ai muốn lặp qua tất cả các chuỗi truy vấn từ một chuỗi

        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
        }


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.