Làm cách nào để tạo chuỗi truy vấn cho URL trong C #?


473

Một tác vụ phổ biến khi gọi tài nguyên web từ mã là xây dựng chuỗi truy vấn để bao gồm tất cả các tham số cần thiết. Mặc dù bằng mọi cách không có khoa học tên lửa, có một số chi tiết tiện lợi bạn cần quan tâm như thế, nối thêm &nếu không phải là tham số đầu tiên, mã hóa các tham số, v.v.

Mã để làm điều đó rất đơn giản, nhưng hơi tẻ nhạt:

StringBuilder SB = new StringBuilder();
if (NeedsToAddParameter A) 
{ 
  SB.Append("A="); SB.Append(HttpUtility.UrlEncode("TheValueOfA")); 
}

if (NeedsToAddParameter B) 
{
  if (SB.Length>0) SB.Append("&"); 
  SB.Append("B="); SB.Append(HttpUtility.UrlEncode("TheValueOfB")); }
}

Đây là một nhiệm vụ phổ biến như vậy người ta sẽ mong đợi một lớp tiện ích tồn tại làm cho nó thanh lịch và dễ đọc hơn. Quét MSDN, tôi thất bại trong việc tìm kiếm một câu hỏi đưa tôi đến câu hỏi sau:

Cách làm sạch thanh lịch nhất mà bạn biết làm như trên là gì?


26
Có một chút buồn là ngay cả tại thời điểm hiện tại, dường như không có cách nào đơn giản để đối phó với các truy vấn. Và đơn giản, tôi muốn nói đến một lớp khung công tác tuân thủ tiêu chuẩn OOB, không nội bộ. Hoặc có thể tôi đang bỏ lỡ một cái gì đó?
Nỗi sợ hãi của sự tuyệt vọng

5
Bạn không thiếu thứ gì. Xây dựng chuỗi truy vấn là một khoảng trống lớn trong khung mà tôi đã cố gắng lấp đầy bằng Flurl .
Todd Menier


Bạn vừa khiến tôi nghĩ rằng tôi nên xây dựng một .. UrlBuilder mới (hiện có) .AddQuery ("key", "value"). ToString ()
Demetris Leptos

Câu trả lời:


293

Nếu bạn nhìn dưới mui xe, thuộc tính QueryString là NameValueCollection. Khi tôi đã thực hiện những điều tương tự, tôi thường quan tâm đến việc tuần tự hóa và giải trừ, vì vậy đề xuất của tôi là xây dựng một NameValueCollection và sau đó chuyển đến:

using System.Linq;
using System.Web;
using System.Collections.Specialized;

private string ToQueryString(NameValueCollection nvc)
{
    var array = (
        from key in nvc.AllKeys
        from value in nvc.GetValues(key)
            select string.Format(
                "{0}={1}",
                HttpUtility.UrlEncode(key),
                HttpUtility.UrlEncode(value))
        ).ToArray();
    return "?" + string.Join("&", array);
}

Tôi tưởng tượng có một cách siêu thanh lịch để làm điều này trong LINQ nữa ...


22
Thông số HTTP (RFC 2616) không nói gì về chuỗi truy vấn có thể chứa. RFC 3986 cũng không xác định định dạng URI chung. Định dạng cặp khóa / giá trị thường được sử dụng được gọi application/x-www-form-urlencodedvà thực sự được xác định bởi HTML, với mục đích gửi dữ liệu biểu mẫu như một phần của GETyêu cầu. HTML 5 không cấm nhiều giá trị cho mỗi khóa theo định dạng này và trên thực tế, nó yêu cầu trình duyệt tạo ra nhiều giá trị cho mỗi khóa trong trường hợp trang (không chính xác) chứa nhiều trường có cùng namethuộc tính. Xem goo.gl/uk1Ag
Daniel Cassidy

14
@annakata: Tôi biết nhận xét của mình đã hơn một năm tuổi (và câu trả lời hơn hai năm tuổi!), nhưng NameValueCollection hỗ trợ rất nhiều giá trị cho mỗi khóa, bằng cách sử dụng phương thức GetValues ​​(khóa).
Mauricio Scheffer

4
@MauricioScheffer: Nhưng NameValueCollection không chuyển đổi thành một chuỗi truy vấn "chính xác". Ví dụ: nếu bạn đặt tham số QueryString trên WebClient trong đó cùng một khóa xuất hiện nhiều lần, nó sẽ biến thành "path? Key = value1, value2" thay vì "path? Key = value1 & key = value2", là một phổ biến (tiêu chuẩn ?) mẫu.
David Pope

8
Về nhiều giá trị cho mỗi khóa, tôi tin rằng trong HTML, nếu bạn có hộp danh sách đa lựa chọn với nhiều mục được chọn và gửi, chúng sẽ được gửi theo định dạng nhiều giá trị được đề cập bởi David.
Sam

10
Bạn có thể muốn sử dụng Uri.EscapeDataString thay vì HttpUtility.UrlEncode dễ mang theo hơn. Xem stackoverflow.com/questions/2573290/
Mạnh

687

Bạn có thể tạo một ví dụ có thể ghi mới HttpValueCollectionbằng cách gọi System.Web.HttpUtility.ParseQueryString(string.Empty)và sau đó sử dụng nó như bất kỳ NameValueCollection. Khi bạn đã thêm các giá trị bạn muốn, bạn có thể gọi ToStringvào bộ sưu tập để nhận chuỗi truy vấn, như sau:

NameValueCollection queryString = System.Web.HttpUtility.ParseQueryString(string.Empty);

queryString.Add("key1", "value1");
queryString.Add("key2", "value2");

return queryString.ToString(); // Returns "key1=value1&key2=value2", all URL-encoded

Đây HttpValueCollectionlà nội bộ và do đó bạn không thể trực tiếp xây dựng một thể hiện. Tuy nhiên, một khi bạn có được một thể hiện, bạn có thể sử dụng nó như bất kỳ ví dụ nào khác NameValueCollection. Vì đối tượng thực tế mà bạn đang làm việc là một HttpValueCollection, nên gọi phương thức ToString sẽ gọi phương thức được ghi đè trên HttpValueCollection, định dạng bộ sưu tập dưới dạng chuỗi truy vấn được mã hóa URL.

Sau khi tìm kiếm SO và web để tìm câu trả lời cho một vấn đề tương tự, đây là giải pháp đơn giản nhất tôi có thể tìm thấy.

Lõi .NET

Nếu bạn đang làm việc trong .NET Core, bạn có thể sử dụng Microsoft.AspNetCore.WebUtilities.QueryHelperslớp, điều này giúp đơn giản hóa việc này rất nhiều.

https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.webutilities.queryhelpers

Mã mẫu:

const string url = "https://customer-information.azure-api.net/customers/search/taxnbr";
var param = new Dictionary<string, string>() { { "CIKey", "123456789" } };

var newUrl = new Uri(QueryHelpers.AddQueryString(url, param));

6
Bạn có thể có thể tạo một phương thức mở rộng có tên ToURLQueryString cho giao diện IDadata:public static string ToURLQueryString(this IDictionary dict) { ... }
Roy Tinker

65
Phương pháp này không tuân thủ tiêu chuẩn cho các ký tự đa bào. Nó sẽ mã hóa chúng dưới dạng% uXXXX thay vì% XX% XX. Chuỗi truy vấn kết quả có thể được giải thích không chính xác bởi các máy chủ web. Điều này thậm chí còn được ghi lại trong lớp khung nội bộ httpValueCollection được trả về bởi HttpUtility.PudeQueryString (). Bình luận nói rằng họ giữ hành vi này vì lý do tương thích ngược.
alex

25
Lưu ý rằng có một sự khác biệt quan trọng giữa HttpUtilityPraseQueryString ("") và NameValueCollection () mới - chỉ kết quả httpUtility sẽ ghi đè ToString () để tạo ra một chuỗi truy vấn phù hợp
Frank Schwieterman

7
Còn trường hợp bạn muốn nhiều trường hợp tên trong chuỗi truy vấn thì sao? Ví dụ: "loại = 10 & loại = 21".
Finster

7
@Finster Bạn có thể thêm nhiều phiên bản của tên vào chuỗi truy vấn bằng Addphương thức. Tức là queryString.Add("type", "1"); queryString.Add("type", "2"); sử dụng Addphương pháp có lẽ là một cách tốt hơn để thực hiện điều này mọi lúc.
jeremysawgie

94

Với cảm hứng từ nhận xét của Roy Tinker, cuối cùng tôi đã sử dụng một phương thức mở rộng đơn giản trên lớp Uri để giữ cho mã của tôi ngắn gọn và sạch sẽ:

using System.Web;

public static class HttpExtensions
{
    public static Uri AddQuery(this Uri uri, string name, string value)
    {
        var httpValueCollection = HttpUtility.ParseQueryString(uri.Query);

        httpValueCollection.Remove(name);
        httpValueCollection.Add(name, value);

        var ub = new UriBuilder(uri);
        ub.Query = httpValueCollection.ToString();

        return ub.Uri;
    }
}

Sử dụng:

Uri url = new Uri("http://localhost/rest/something/browse").
          AddQuery("page", "0").
          AddQuery("pageSize", "200");

Chỉnh sửa - Biến thể tuân thủ tiêu chuẩn

Như nhiều người đã chỉ ra, httpValueCollection.ToString()mã hóa các ký tự Unicode theo cách không tuân thủ tiêu chuẩn . Đây là một biến thể của cùng một phương thức mở rộng xử lý các ký tự như vậy bằng cách gọi HttpUtility.UrlEncodephương thức thay vì HttpUtility.UrlEncodeUnicodephương thức không dùng nữa .

using System.Web;

public static Uri AddQuery(this Uri uri, string name, string value)
{
    var httpValueCollection = HttpUtility.ParseQueryString(uri.Query);

    httpValueCollection.Remove(name);
    httpValueCollection.Add(name, value);

    var ub = new UriBuilder(uri);

    // this code block is taken from httpValueCollection.ToString() method
    // and modified so it encodes strings with HttpUtility.UrlEncode
    if (httpValueCollection.Count == 0)
        ub.Query = String.Empty;
    else
    {
        var sb = new StringBuilder();

        for (int i = 0; i < httpValueCollection.Count; i++)
        {
            string text = httpValueCollection.GetKey(i);
            {
                text = HttpUtility.UrlEncode(text);

                string val = (text != null) ? (text + "=") : string.Empty;
                string[] vals = httpValueCollection.GetValues(i);

                if (sb.Length > 0)
                    sb.Append('&');

                if (vals == null || vals.Length == 0)
                    sb.Append(val);
                else
                {
                    if (vals.Length == 1)
                    {
                        sb.Append(val);
                        sb.Append(HttpUtility.UrlEncode(vals[0]));
                    }
                    else
                    {
                        for (int j = 0; j < vals.Length; j++)
                        {
                            if (j > 0)
                                sb.Append('&');

                            sb.Append(val);
                            sb.Append(HttpUtility.UrlEncode(vals[j]));
                        }
                    }
                }
            }
        }

        ub.Query = sb.ToString();
    }

    return ub.Uri;
}

3
Hoàn hảo. Thêm vào thư viện trong nhà của tôi. :)
Andy

1
Bạn cũng nên mã hóa URL giá trị. queryString.Add (tên, Uri.EscapeDataString (value));
Ufuk Hacıoğulları

2
Cảm ơn đã cải thiện câu trả lời này. Nó đã khắc phục vấn đề với các ký tự đa nhân.
Ufuk Hacıoğulları

9
Lưu ý bên lề, điều này không hoạt động với các url tương đối vì bạn không thể khởi tạo UriBuilder từ một Uri tương đối.
Yuriy Faktorovich

1
Tôi đã thêm khóa xóa để không thể thêm bản sao. dotnetfiddle.net/hTlyAd
Paul Totzke

29

Tôi đã trả lời một câu hỏi tương tự một lúc trước. Về cơ bản, cách tốt nhất sẽ là sử dụng lớp HttpValueCollection, mà thuộc Request.QueryStringtính của ASP.NET thực sự là, không may nó là nội bộ trong khung .NET. Bạn có thể sử dụng Reflector để lấy nó (và đặt nó vào lớp Utils của bạn). Bằng cách này, bạn có thể thao tác chuỗi truy vấn như NameValueCollection, nhưng với tất cả các vấn đề về mã hóa / giải mã url được chăm sóc cho bạn.

HttpValueCollectionmở rộng NameValueCollectionvà có một hàm tạo có một chuỗi truy vấn được mã hóa (bao gồm cả dấu và dấu hỏi) và nó ghi đè một ToString()phương thức để sau đó xây dựng lại chuỗi truy vấn từ bộ sưu tập bên dưới.

Thí dụ:

  var coll = new HttpValueCollection();

  coll["userId"] = "50";
  coll["paramA"] = "A";
  coll["paramB"] = "B";      

  string query = coll.ToString(true); // true means use urlencode

  Console.WriteLine(query); // prints: userId=50&paramA=A&paramB=B

Cảm ơn bạn ... tôi nhận thấy rằng NameValueCollection mà nó trả về có ToString () hoạt động khác nhau nhưng không thể hiểu tại sao.
calebt

httpValueCollection.ToString()thực sự gọi httpValueCollection.ToString(true)như vậy để thêm sự khám phá truelà không cần thiết.
dav_i

5
HttpValueCollection là một lớp bên trong do đó bạn không thể khởi tạo nó.
ozba

29

Đây là một cách thông thạo / lambda-ish như một phương thức mở rộng (kết hợp các khái niệm trong các bài viết trước) hỗ trợ nhiều giá trị cho cùng một khóa. Sở thích cá nhân của tôi là các tiện ích mở rộng trên các trình bao bọc cho khả năng khám phá của các thành viên khác trong nhóm đối với những thứ như thế này. Lưu ý rằng có nhiều tranh cãi xung quanh các phương thức mã hóa, rất nhiều bài đăng về nó trên Stack Overflow (một bài như vậy ) và các blogger MSDN (như bài này ).

public static string ToQueryString(this NameValueCollection source)
{
    return String.Join("&", source.AllKeys
        .SelectMany(key => source.GetValues(key)
            .Select(value => String.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value))))
        .ToArray());
}

chỉnh sửa: với sự hỗ trợ null, mặc dù có thể bạn sẽ cần điều chỉnh nó cho tình huống cụ thể của mình

public static string ToQueryString(this NameValueCollection source, bool removeEmptyEntries)
{
    return source != null ? String.Join("&", source.AllKeys
        .Where(key => !removeEmptyEntries || source.GetValues(key)
            .Where(value => !String.IsNullOrEmpty(value))
            .Any())
        .SelectMany(key => source.GetValues(key)
            .Where(value => !removeEmptyEntries || !String.IsNullOrEmpty(value))
            .Select(value => String.Format("{0}={1}", HttpUtility.UrlEncode(key), value != null ? HttpUtility.UrlEncode(value) : string.Empty)))
        .ToArray())
        : string.Empty;
}

1
Điều này không thành công nếu bất kỳ giá trị nào là null
Josh Noe

Điều này là sai, nó tạo ra nhiều chuỗi truy vấn cho mỗi cặp giá trị khóa
Gayan

@GayanRanasinghe: Điều đó có nghĩa là gì?
Matti Virkkunen

22

Flurl [tiết lộ: Tôi là tác giả] hỗ trợ xây dựng chuỗi truy vấn thông qua các đối tượng ẩn danh (trong số các cách khác):

var url = "http://www.some-api.com".SetQueryParams(new
{
    api_key = ConfigurationManager.AppSettings["SomeApiKey"],
    max_results = 20,
    q = "Don't worry, I'll get encoded!"
});

Lib đồng hành tùy chọn Flurl.Http cho phép bạn thực hiện các cuộc gọi HTTP ngay từ cùng một chuỗi cuộc gọi trôi chảy, mở rộng nó thành một máy khách REST đầy đủ:

T result = await "https://api.mysite.com"
    .AppendPathSegment("person")
    .SetQueryParams(new { ap_key = "my-key" })
    .WithOAuthBearerToken("MyToken")
    .PostJsonAsync(new { first_name = firstName, last_name = lastName })
    .ReceiveJson<T>();

Gói đầy đủ có sẵn trên NuGet:

PM> Install-Package Flurl.Http

hoặc chỉ là trình tạo URL độc lập:

PM> Install-Package Flurl


20

Đây là mục nhập muộn của tôi. Tôi không thích bất kỳ ai khác vì những lý do khác nhau, vì vậy tôi đã tự viết.

Phiên bản này có tính năng:

  • Chỉ sử dụng StringBuilder. Không có cuộc gọi ToArray () hoặc các phương thức mở rộng khác. Nó trông không đẹp như một số phản hồi khác, nhưng tôi coi đây là chức năng cốt lõi nên hiệu quả quan trọng hơn việc có mã "lưu loát", "một lớp" che giấu sự thiếu hiệu quả.

  • Xử lý nhiều giá trị cho mỗi khóa. (Không cần bản thân mình mà chỉ im lặng Mauricio;)

    public string ToQueryString(NameValueCollection nvc)
    {
        StringBuilder sb = new StringBuilder("?");
    
        bool first = true;
    
        foreach (string key in nvc.AllKeys)
        {
            foreach (string value in nvc.GetValues(key))
            {
                if (!first)
                {
                    sb.Append("&");
                }
    
                sb.AppendFormat("{0}={1}", Uri.EscapeDataString(key), Uri.EscapeDataString(value));
    
                first = false;
            }
        }
    
        return sb.ToString();
    }

Cách sử dụng ví dụ

        var queryParams = new NameValueCollection()
        {
            { "x", "1" },
            { "y", "2" },
            { "foo", "bar" },
            { "foo", "baz" },
            { "special chars", "? = &" },
        };

        string url = "http://example.com/stuff" + ToQueryString(queryParams);

        Console.WriteLine(url);

Đầu ra

http://example.com/stuff?x=1&y=2&foo=bar&foo=baz&special%20chars=%3F%20%3D%20%26

Tôi thích điều này không sử dụng HttpUtility trong System.Web và không có sẵn ở mọi nơi.
Kugel

+1 vì không sử dụng linq và không sử dụng HttpUtility. Tôi sẽ tạo một sb trống và bỏ qua biến "bool first" và sau đó trong vòng lặp chỉ cần có sb.Append (sb.Lạng == 0? "?": "&") Trước sb.AppendFormat (). Bây giờ nếu nvc trống, phương thức sẽ trả về một chuỗi rỗng thay vì "?" Cô đơn.
Mathew Leger

Câu trả lời này xử lý các tham số đơn với nhiều giá trị. ví dụ: id = 1 & id = 3 & id = 2 & id = 9
Mathemats

12

Làm thế nào về việc tạo các phương thức mở rộng cho phép bạn thêm các tham số theo kiểu trôi chảy như thế này?

string a = "http://www.somedomain.com/somepage.html"
    .AddQueryParam("A", "TheValueOfA")
    .AddQueryParam("B", "TheValueOfB")
    .AddQueryParam("Z", "TheValueOfZ");

string b = new StringBuilder("http://www.somedomain.com/anotherpage.html")
    .AddQueryParam("A", "TheValueOfA")
    .AddQueryParam("B", "TheValueOfB")
    .AddQueryParam("Z", "TheValueOfZ")
    .ToString(); 

Đây là tình trạng quá tải sử dụng string:

public static string AddQueryParam(
    this string source, string key, string value)
{
    string delim;
    if ((source == null) || !source.Contains("?"))
    {
        delim = "?";
    }
    else if (source.EndsWith("?") || source.EndsWith("&"))
    {
        delim = string.Empty;
    }
    else
    {
        delim = "&";
    }

    return source + delim + HttpUtility.UrlEncode(key)
        + "=" + HttpUtility.UrlEncode(value);
}

Và đây là tình trạng quá tải sử dụng StringBuilder:

public static StringBuilder AddQueryParam(
    this StringBuilder source, string key, string value)
{
    bool hasQuery = false;
    for (int i = 0; i < source.Length; i++)
    {
        if (source[i] == '?')
        {
            hasQuery = true;
            break;
        }
    }

    string delim;
    if (!hasQuery)
    {
        delim = "?";
    }
    else if ((source[source.Length - 1] == '?')
        || (source[source.Length - 1] == '&'))
    {
        delim = string.Empty;
    }
    else
    {
        delim = "&";
    }

    return source.Append(delim).Append(HttpUtility.UrlEncode(key))
        .Append("=").Append(HttpUtility.UrlEncode(value));
}

: +1: cho phương thức mở rộng dựa trên Chuỗi đơn giản. Một số câu trả lời khác có thể bao gồm nhiều trường hợp cạnh, nhưng điều này là đủ cho hoàn cảnh của tôi, và nó không yêu cầu tôi để xây dựng một NameValueCollection, HttpValueCollectionhoặc một Uriđầu tiên. Cảm ơn!
Stanley G.

11

Tôi cần giải quyết vấn đề tương tự cho một thư viện lớp di động (PCL) mà tôi đang làm việc. Trong trường hợp này, tôi không có quyền truy cập vào System.Web vì vậy tôi không thể sử dụng ParseQueryString.

Thay vào đó tôi đã sử dụng System.Net.Http.FormUrlEncodedContentnhư vậy:

var url = new UriBuilder("http://example.com");

url.Query = new FormUrlEncodedContent(new Dictionary<string,string>()
{
    {"param1", "val1"},
    {"param2", "val2"},
    {"param3", "val3"},
}).ReadAsStringAsync().Result;

Đây là kỹ thuật tôi sử dụng và đã tham chiếu nó trong một câu hỏi khác http://stackoverflow.com/a/26744471/2108310 Sự khác biệt duy nhất là tôi sử dụng một mảng các cặp KeyValue ... ngoài việc cần tham chiếu đến Hệ thống. Net (có sẵn PCL như bạn đã nêu) đây là IMHO cách đơn giản nhất để thực hiện mà không bao gồm gói bên thứ ba nào đó, hoặc cố gắng trộn lẫn một số mớ spaghetti homebrew.
Rostov

9
    public static string ToQueryString(this Dictionary<string, string> source)
    {
        return String.Join("&", source.Select(kvp => String.Format("{0}={1}", HttpUtility.UrlEncode(kvp.Key), HttpUtility.UrlEncode(kvp.Value))).ToArray());
    }

    public static string ToQueryString(this NameValueCollection source)
    {
        return String.Join("&", source.Cast<string>().Select(key => String.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(source[key]))).ToArray());
    }

1
Đẹp! Nhưng bạn không cần .ToArray()s.
mở

7

Thêm lớp này vào dự án của bạn

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

public class QueryStringBuilder
{
    private readonly List<KeyValuePair<string, object>> _list;

    public QueryStringBuilder()
    {
        _list = new List<KeyValuePair<string, object>>();
    }

    public void Add(string name, object value)
    {
        _list.Add(new KeyValuePair<string, object>(name, value));
    }

    public override string ToString()
    {
        return String.Join("&", _list.Select(kvp => String.Concat(Uri.EscapeDataString(kvp.Key), "=", Uri.EscapeDataString(kvp.Value.ToString()))));
    }
}

Và sử dụng nó như thế này:

var actual = new QueryStringBuilder {
    {"foo", 123},
    {"bar", "val31"},
    {"bar", "val32"}
};

actual.Add("a+b", "c+d");

actual.ToString(); // "foo=123&bar=val31&bar=val32&a%2bb=c%2bd"

Bây giờ, đây phải là câu trả lời được chấp nhận; hoạt động hoàn hảo cho các mảng như "foo [] = 1, foo [] = 2" cũng như giữ thứ tự các tham số rất quan trọng.
Soroush Falahati

6

Cung cấp của tôi:

public static Uri AddQuery(this Uri uri, string name, string value)
{
    // this actually returns HttpValueCollection : NameValueCollection
    // which uses unicode compliant encoding on ToString()
    var query = HttpUtility.ParseQueryString(uri.Query);

    query.Add(name, value);

    var uriBuilder = new UriBuilder(uri)
    {
        Query = query.ToString()
    };

    return uriBuilder.Uri;
}

Sử dụng:

var uri = new Uri("http://stackoverflow.com").AddQuery("such", "method")
                                             .AddQuery("wow", "soFluent");

// http://stackoverflow.com?such=method&wow=soFluent

Tôi thích cách tiếp cận của bạn Đơn giản và Thanh lịch, Tuy nhiên, HttpUtility yêu cầu System.Web
Ody

5

Chưa được kiểm tra, nhưng tôi nghĩ một cái gì đó dọc theo những dòng này sẽ hoạt động khá độc đáo

public class QueryString
{
    private Dictionary<string,string> _Params = new Dictionary<string,string>();

    public overide ToString()
    {
        List<string> returnParams = new List<string>();

        foreach (KeyValuePair param in _Params)
        {
            returnParams.Add(String.Format("{0}={1}", param.Key, param.Value));
        }

        // return String.Format("?{0}", String.Join("&", returnParams.ToArray())); 

        // credit annakata
        return "?" + String.Join("&", returnParams.ToArray());
    }

    public void Add(string key, string value)
    {
        _Params.Add(key, HttpUtility.UrlEncode(value));
    }
}

QueryString query = new QueryString();

query.Add("param1", "value1");
query.Add("param2", "value2");

return query.ToString();

được đóng gói độc đáo nhưng định dạng trên "? {0}" là loại đắt tiền không cần thiết :)
annakata

đã thay đổi tên lớp thành QueryString .. Truy vấn hơi mơ hồ
Nick Allen

4

Một phiên bản dựa trên phương pháp mở rộng nhanh:

class Program
{
    static void Main(string[] args)
    {
        var parameters = new List<KeyValuePair<string, string>>
                             {
                                 new KeyValuePair<string, string>("A", "AValue"),
                                 new KeyValuePair<string, string>("B", "BValue")
                             };

        string output = "?" + string.Join("&", parameters.ConvertAll(param => param.ToQueryString()).ToArray());
    }
}

public static class KeyValueExtensions
{
    public static string ToQueryString(this KeyValuePair<string, string> obj)
    {
        return obj.Key + "=" + HttpUtility.UrlEncode(obj.Value);
    }
}

Bạn có thể sử dụng mệnh đề where để chọn tham số nào được thêm vào chuỗi.


3

Giả sử rằng bạn muốn giảm sự phụ thuộc vào các hội đồng khác và để mọi thứ đơn giản, bạn có thể làm:

var sb = new System.Text.StringBuilder();

sb.Append("a=" + HttpUtility.UrlEncode("TheValueOfA") + "&");
sb.Append("b=" + HttpUtility.UrlEncode("TheValueOfB") + "&");
sb.Append("c=" + HttpUtility.UrlEncode("TheValueOfC") + "&");
sb.Append("d=" + HttpUtility.UrlEncode("TheValueOfD") + "&");

sb.Remove(sb.Length-1, 1); // Remove the final '&'

string result = sb.ToString();

Điều này hoạt động tốt với các vòng lặp quá. Việc loại bỏ ampersand cuối cùng cần phải đi ra ngoài vòng lặp.

Lưu ý rằng toán tử ghép được sử dụng để cải thiện khả năng đọc. Chi phí sử dụng nó so với chi phí sử dụng StringBuilder là tối thiểu (tôi nghĩ Jeff Atwood đã đăng một cái gì đó về chủ đề này).


3

Kết hợp các câu trả lời hàng đầu để tạo phiên bản đối tượng ẩn danh :

var queryString = HttpUtility2.BuildQueryString(new
{
    key2 = "value2",
    key1 = "value1",
});

Điều đó tạo ra điều này:

key2 = value2 & key1 = value1

Đây là mã:

public static class HttpUtility2
{
    public static string BuildQueryString<T>(T obj)
    {
        var queryString = HttpUtility.ParseQueryString(string.Empty);

        foreach (var property in TypeDescriptor.GetProperties(typeof(T)).Cast<PropertyDescriptor>())
        {
            var value = (property.GetValue(obj) ?? "").ToString();
            queryString.Add(property.Name, value);
        }

        return queryString.ToString();
    }
}

2

Tương tự như giải pháp được chấp nhận, nhưng được chuyển sang cú pháp LINQ "chấm" ...

private string ToQueryString(NameValueCollection nvc)
{
    if (nvc == null) return String.Empty;
    var queryParams = 
          string.Join("&", nvc.AllKeys.Select(key => 
              string.Join("&", nvc.GetValues(key).Select(v => string.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(v))))));
    return "?" + queryParams;
}

2

Tôi có một phương thức mở rộng cho Uri rằng:

  • Chấp nhận các đối tượng ẩn danh: uri.WithQuery(new { name = "value" })
  • Chấp nhận bộ sưu tập các string/stringcặp (ví dụ: Dictionary`2 ).
  • Chấp nhận bộ sưu tập các string/objectcặp (ví dụ: RouteValueDipedia ).
  • Chấp nhận NameValueCollection s.
  • Sắp xếp các giá trị truy vấn theo khóa để các giá trị tương tự tạo ra các URI bằng nhau.
  • Hỗ trợ nhiều giá trị cho mỗi khóa, duy trì thứ tự ban đầu của chúng.

Các phiên bản tài liệu có thể được tìm thấy ở đây .

Phần mở rộng:

public static Uri WithQuery(this Uri uri, object values)
{
    if (uri == null)
        throw new ArgumentNullException(nameof(uri));

    if (values != null)
    {
        var query = string.Join(
            "&", from p in ParseQueryValues(values)
                 where !string.IsNullOrWhiteSpace(p.Key)
                 let k = HttpUtility.UrlEncode(p.Key.Trim())
                 let v = HttpUtility.UrlEncode(p.Value)
                 orderby k
                 select string.IsNullOrEmpty(v) ? k : $"{k}={v}");

        if (query.Length != 0 || uri.Query.Length != 0)
            uri = new UriBuilder(uri) { Query = query }.Uri;
    }

    return uri;
}

Trình phân tích cú pháp truy vấn:

private static IEnumerable<KeyValuePair<string, string>> ParseQueryValues(object values)
{
    // Check if a name/value collection.
    var nvc = values as NameValueCollection;
    if (nvc != null)
        return from key in nvc.AllKeys
               from val in nvc.GetValues(key)
               select new KeyValuePair<string, string>(key, val);

    // Check if a string/string dictionary.
    var ssd = values as IEnumerable<KeyValuePair<string, string>>;
    if (ssd != null)
        return ssd;

    // Check if a string/object dictionary.
    var sod = values as IEnumerable<KeyValuePair<string, object>>;
    if (sod == null)
    {
        // Check if a non-generic dictionary.
        var ngd = values as IDictionary;
        if (ngd != null)
            sod = ngd.Cast<dynamic>().ToDictionary<dynamic, string, object>(
                p => p.Key.ToString(), p => p.Value as object);

        // Convert object properties to dictionary.
        if (sod == null)
            sod = new RouteValueDictionary(values);
    }

    // Normalize and return the values.
    return from pair in sod
           from val in pair.Value as IEnumerable<string>
            ?? new[] { pair.Value?.ToString() }
           select new KeyValuePair<string, string>(pair.Key, val);
}

Dưới đây là các bài kiểm tra:

var uri = new Uri("https://stackoverflow.com/yo?oldKey=oldValue");

// Test with a string/string dictionary.
var q = uri.WithQuery(new Dictionary<string, string>
{
    ["k1"] = string.Empty,
    ["k2"] = null,
    ["k3"] = "v3"
});

Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?k1&k2&k3=v3"));

// Test with a string/object dictionary.
q = uri.WithQuery(new Dictionary<string, object>
{
    ["k1"] = "v1",
    ["k2"] = new[] { "v2a", "v2b" },
    ["k3"] = null
});

Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?k1=v1&k2=v2a&k2=v2b&k3"));

// Test with a name/value collection.
var nvc = new NameValueCollection()
{
    ["k1"] = string.Empty,
    ["k2"] = "v2a"
};

nvc.Add("k2", "v2b");

q = uri.WithQuery(nvc);
Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?k1&k2=v2a&k2=v2b"));

// Test with any dictionary.
q = uri.WithQuery(new Dictionary<int, HashSet<string>>
{
    [1] = new HashSet<string> { "v1" },
    [2] = new HashSet<string> { "v2a", "v2b" },
    [3] = null
});

Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?1=v1&2=v2a&2=v2b&3"));

// Test with an anonymous object.
q = uri.WithQuery(new
{
    k1 = "v1",
    k2 = new[] { "v2a", "v2b" },
    k3 = new List<string> { "v3" },
    k4 = true,
    k5 = null as Queue<string>
});

Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?k1=v1&k2=v2a&k2=v2b&k3=v3&k4=True&k5"));

// Keep existing query using a name/value collection.
nvc = HttpUtility.ParseQueryString(uri.Query);
nvc.Add("newKey", "newValue");

q = uri.WithQuery(nvc);
Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?newKey=newValue&oldKey=oldValue"));

// Merge two query objects using the RouteValueDictionary.
var an1 = new { k1 = "v1" };
var an2 = new { k2 = "v2" };

q = uri.WithQuery(
    new RouteValueDictionary(an1).Concat(
        new RouteValueDictionary(an2)));

Debug.Assert(q == new Uri(
    "https://stackoverflow.com/yo?k1=v1&k2=v2"));

2

Lớp trình bao bọc có khả năng chuỗi cho httpValueCollection:

namespace System.Web.Mvc {
    public class QueryStringBuilder {
        private NameValueCollection collection;
        public QueryStringBuilder() {
            collection = System.Web.HttpUtility.ParseQueryString(string.Empty);
        }
        public QueryStringBuilder Add(string key, string value) {
            collection.Add(key, value);
            return this;
        }
        public QueryStringBuilder Remove(string key) {
            collection.Remove(key);
            return this;
        }
        public string this[string key] {
            get { return collection[key]; }
            set { collection[key] = value; }
        }
        public string ToString() {
            return collection.ToString();
        }
    }
}

Ví dụ sử dụng:

QueryStringBuilder parameters = new QueryStringBuilder()
    .Add("view", ViewBag.PageView)
    .Add("page", ViewBag.PageNumber)
    .Add("size", ViewBag.PageSize);
string queryString = parameters.ToString();

1

Tôi đã thêm phương thức sau vào lớp PageBase của mình.

protected void Redirect(string url)
    {
        Response.Redirect(url);
    }
protected void Redirect(string url, NameValueCollection querystrings)
    {
        StringBuilder redirectUrl = new StringBuilder(url);

        if (querystrings != null)
        {
            for (int index = 0; index < querystrings.Count; index++)
            {
                if (index == 0)
                {
                    redirectUrl.Append("?");
                }

                redirectUrl.Append(querystrings.Keys[index]);
                redirectUrl.Append("=");
                redirectUrl.Append(HttpUtility.UrlEncode(querystrings[index]));

                if (index < querystrings.Count - 1)
                {
                    redirectUrl.Append("&");
                }
            }
        }

        this.Redirect(redirectUrl.ToString());
    }

Để gọi:

NameValueCollection querystrings = new NameValueCollection();    
querystrings.Add("language", "en");
querystrings.Add("id", "134");
this.Redirect("http://www.mypage.com", querystrings);

1

Tôi đã viết một số phương thức mở rộng mà tôi thấy rất hữu ích khi làm việc với QueryStrings. Thường thì tôi muốn bắt đầu với QueryString hiện tại và sửa đổi trước khi sử dụng nó. Cái gì đó như,

var res = Request.QueryString.Duplicate()
  .ChangeField("field1", "somevalue")
  .ChangeField("field2", "only if following is true", true)
  .ChangeField("id", id, id>0)
  .WriteLocalPathWithQuery(Request.Url)); //Uses context to write the path

Để biết thêm và nguồn: http://www.charlesrcook.com/archive/2008/07/23/c-extension-methods-for-asp.net-query-opes-operations.aspx

Đó là cơ bản, nhưng tôi thích phong cách.


1

Chỉ muốn ném vào 2 xu của tôi:

public static class HttpClientExt
{
    public static Uri AddQueryParams(this Uri uri, string query)
    {
        var ub = new UriBuilder(uri);
        ub.Query = string.IsNullOrEmpty(uri.Query) ? query : string.Join("&", uri.Query.Substring(1), query);
        return ub.Uri;
    }

    public static Uri AddQueryParams(this Uri uri, IEnumerable<string> query)
    {
        return uri.AddQueryParams(string.Join("&", query));
    } 

    public static Uri AddQueryParams(this Uri uri, string key, string value)
    {
        return uri.AddQueryParams(string.Join("=", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value)));
    }

    public static Uri AddQueryParams(this Uri uri, params KeyValuePair<string,string>[] kvps)
    {
        return uri.AddQueryParams(kvps.Select(kvp => string.Join("=", HttpUtility.UrlEncode(kvp.Key), HttpUtility.UrlEncode(kvp.Value))));
    }

    public static Uri AddQueryParams(this Uri uri, IDictionary<string, string> kvps)
    {
        return uri.AddQueryParams(kvps.Select(kvp => string.Join("=", HttpUtility.UrlEncode(kvp.Key), HttpUtility.UrlEncode(kvp.Value))));
    }

    public static Uri AddQueryParams(this Uri uri, NameValueCollection nvc)
    {
        return uri.AddQueryParams(nvc.AllKeys.SelectMany(nvc.GetValues, (key, value) => string.Join("=", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value))));
    }
}

Các tài liệu nói rằng uri.Querysẽ bắt đầu bằng một ?nếu nó không trống và bạn nên cắt bỏ nó nếu bạn sẽ sửa đổi nó.

Lưu ý rằng HttpUtility.UrlEncodeđược tìm thấy trong System.Web.

Sử dụng:

var uri = new Uri("https://api.del.icio.us/v1/posts/suggest").AddQueryParam("url","http://stackoverflow.com")

1

Mặc dù không thanh lịch, tôi đã chọn một phiên bản đơn giản hơn không sử dụng NameValueCollecitons- chỉ là một mẫu xây dựng bao quanh StringBuilder.

public class UrlBuilder
{
    #region Variables / Properties

    private readonly StringBuilder _builder;

    #endregion Variables / Properties

    #region Constructor

    public UrlBuilder(string urlBase)
    {
        _builder = new StringBuilder(urlBase);
    }

    #endregion Constructor

    #region Methods

    public UrlBuilder AppendParameter(string paramName, string value)
    {
        if (_builder.ToString().Contains("?"))
            _builder.Append("&");
        else
            _builder.Append("?");

        _builder.Append(HttpUtility.UrlEncode(paramName));
        _builder.Append("=");
        _builder.Append(HttpUtility.UrlEncode(value));

        return this;
    }

    public override string ToString()
    {
        return _builder.ToString();
    }

    #endregion Methods
}

Mỗi câu trả lời hiện có, tôi chắc chắn sử dụng HttpUtility.UrlEncodecác cuộc gọi. Nó được sử dụng như vậy:

string url = new UrlBuilder("http://www.somedomain.com/")
             .AppendParameter("a", "true")
             .AppendParameter("b", "muffin")
             .AppendParameter("c", "muffin button")
             .ToString();
// Result: http://www.somedomain.com?a=true&b=muffin&c=muffin%20button

1
// USAGE
[TestMethod]
public void TestUrlBuilder()
{
    Console.WriteLine(
        new UrlBuilder("http://www.google.com?A=B")
            .AddPath("SomePathName")
            .AddPath("AnotherPathName")
            .SetQuery("SomeQueryKey", "SomeQueryValue")
            .AlterQuery("A", x => x + "C"));
}

Đầu ra:

http://www.google.com/SomePathName/AnotherPathName?A=BC&SomeQueryKey=SomeQueryValue

Mật mã; tất cả các bạn có thể cảm ơn tôi ở đâu đó, bằng cách nào đó: D

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

// By Demetris Leptos
namespace TheOperator.Foundation.Web
{
    public class UrlBuilder
    {
        public string Scheme { get; set; }

        public string Host { get; set; }

        public int? Port { get; set; }

        public List<string> Paths { get; set; }

        public SortedDictionary<string, string> QueryPairs { get; set; }

        public UrlBuilder(string url)
        {
            this.Paths = new List<string>();
            this.QueryPairs = new SortedDictionary<string, string>();

            string path = null;
            string query = null;
            Uri relativeUri = null;
            if (!Uri.TryCreate(url, UriKind.Relative, out relativeUri))
            {
                var uriBuilder = new UriBuilder(url);
                this.Scheme = uriBuilder.Scheme;
                this.Host = uriBuilder.Host;
                this.Port = uriBuilder.Port;
                path = uriBuilder.Path;
                query = uriBuilder.Query;
            }
            else
            {
                var queryIndex = url.IndexOf('?');
                if (queryIndex >= 0)
                {
                    path = url.Substring(0, queryIndex);
                    query = url.Substring(queryIndex + 1);
                }
                else
                {
                    path = url;
                }
            }
            this.Paths.AddRange(path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries));
            if (query != null)
            {
                var queryKeyValuePairs = HttpUtility.ParseQueryString(query);
                foreach (var queryKey in queryKeyValuePairs.AllKeys)
                {
                    this.QueryPairs[queryKey] = queryKeyValuePairs[queryKey];
                }
            }
        }

        public UrlBuilder AddPath(string value)
        {
            this.Paths.Add(value);
            return this;
        }

        public UrlBuilder SetQuery(string key, string value)
        {
            this.QueryPairs[key] = value;
            return this;
        }

        public UrlBuilder RemoveQuery(string key)
        {
            this.QueryPairs.Remove(key);
            return this;
        }

        public UrlBuilder AlterQuery(string key, Func<string, string> alterMethod, bool removeOnNull = false)
        {
            string value;
            this.QueryPairs.TryGetValue(key, out value);
            value = alterMethod(value);
            if (removeOnNull && value == null)
            {
                return this.RemoveQuery(key);
            }
            else
            {
                return this.SetQuery(key, value);
            }
        }

        public override string ToString()
        {
            var path = !string.IsNullOrWhiteSpace(this.Host)
                ? string.Join("/", this.Host, string.Join("/", this.Paths))
                : string.Join("/", this.Paths);
            var query = string.Join("&", this.QueryPairs.Select(x => string.Concat(x.Key, "=", HttpUtility.UrlEncode(x.Value))));
            return string.Concat(
                !string.IsNullOrWhiteSpace(this.Scheme) ? string.Concat(this.Scheme, "://") : null,
                path,
                !string.IsNullOrWhiteSpace(query) ? string.Concat("?", query) : null);
        }
    }
}

1

Tôi đã đi với giải pháp được đề xuất bởi DSO (đã trả lời vào ngày 2 tháng 8 năm11 lúc 7:29), giải pháp của anh ấy không yêu cầu sử dụng HttpUtility. Tuy nhiên, theo một bài viết được đăng trên Dotnetpearls , sử dụng Từ điển nhanh hơn (về hiệu suất) so với sử dụng NameValueCollection. Đây là giải pháp của DSO được sửa đổi để sử dụng Từ điển thay cho NameValueCollection.

    public static Dictionary<string, string> QueryParametersDictionary()
    {
        var dictionary = new Dictionary<string, string>();
        dictionary.Add("name", "John Doe");
        dictionary.Add("address.city", "Seattle");
        dictionary.Add("address.state_code", "WA");
        dictionary.Add("api_key", "5352345263456345635");

        return dictionary;
    }

    public static string ToQueryString(Dictionary<string, string> nvc)
    {
        StringBuilder sb = new StringBuilder();

        bool first = true;

        foreach (KeyValuePair<string, string> pair in nvc)
        {
                if (!first)
                {
                    sb.Append("&");
                }

                sb.AppendFormat("{0}={1}", Uri.EscapeDataString(pair.Key), Uri.EscapeDataString(pair.Value));

                first = false;
        }

        return sb.ToString();
    }

1

Chuỗi truy vấn có thể được thêm vào một URL bằng cách:

  1. tạo một đối tượng thu thập giá trị tên
  2. thêm các mục chuỗi truy vấn và giá trị của chúng vào đối tượng này
  3. mã hóa đối tượng thu thập giá trị tên này vào url mã được cung cấp trong liên kết dưới đây

https://blog.codingnovice.com/blog

public ActionResult Create()
{
    //declaring name value collection object
    NameValueCollection collection = new NameValueCollection();

    //adding new value to the name value collection object
    collection.Add("Id1", "wwe323");
    collection.Add("Id2", "454w");
    collection.Add("Id3", "tyt5656");
    collection.Add("Id4", "343wdsd");

    //generating query string
    string url = GenerateQueryString(collection);

    return View();
}

private string GenerateQueryString(NameValueCollection collection)
{
    var querystring = (
        from key in collection.AllKeys
        from value in collection.GetValues(key)
        select string.Format("{0}={1}",
            HttpUtility.UrlEncode(key),
            HttpUtility.UrlEncode(value))
    ).ToArray();
    return "?" + string.Join("&", querystring);
}

0

Tôi đã viết một người trợ giúp cho dự án dao cạo của mình bằng cách sử dụng một số gợi ý từ các câu trả lời khác.

Việc kinh doanh ParseQueryString là cần thiết vì chúng tôi không được phép giả mạo đối tượng QueryString của yêu cầu hiện tại.

@helper GetQueryStringWithValue(string key, string value) {
    var queryString = System.Web.HttpUtility.ParseQueryString(HttpContext.Current.Request.QueryString.ToString());
    queryString[key] = value;
    @Html.Raw(queryString.ToString())
}

Tôi sử dụng nó như thế này:

location.search = '?@Helpers.GetQueryStringWithValue("var-name", "var-value")';

Nếu bạn muốn nó nhận nhiều hơn một giá trị, chỉ cần thay đổi các tham số thành Từ điển và thêm các cặp vào chuỗi truy vấn.


0

Mã dưới đây được gỡ bỏ khi HttpValueCollectionthực hiện ToString, thông qua ILSpy, cung cấp cho bạn một chuỗi truy vấn name = value.

Thật không may, httpValueCollection là một lớp nội bộ mà bạn chỉ nhận được nếu bạn sử dụng HttpUtility.ParseQueryString(). Tôi đã xóa tất cả các phần viewstate cho nó và nó được mã hóa theo mặc định:

public static class HttpExtensions
{
    public static string ToQueryString(this NameValueCollection collection)
    {
        // This is based off the NameValueCollection.ToString() implementation
        int count = collection.Count;
        if (count == 0)
            return string.Empty;

        StringBuilder stringBuilder = new StringBuilder();

        for (int i = 0; i < count; i++)
        {
            string text = collection.GetKey(i);
            text = HttpUtility.UrlEncodeUnicode(text);
            string value = (text != null) ? (text + "=") : string.Empty;
            string[] values = collection.GetValues(i);
            if (stringBuilder.Length > 0)
            {
                stringBuilder.Append('&');
            }
            if (values == null || values.Length == 0)
            {
                stringBuilder.Append(value);
            }
            else
            {
                if (values.Length == 1)
                {
                    stringBuilder.Append(value);
                    string text2 = values[0];
                    text2 = HttpUtility.UrlEncodeUnicode(text2);
                    stringBuilder.Append(text2);
                }
                else
                {
                    for (int j = 0; j < values.Length; j++)
                    {
                        if (j > 0)
                        {
                            stringBuilder.Append('&');
                        }
                        stringBuilder.Append(value);
                        string text2 = values[j];
                        text2 = HttpUtility.UrlEncodeUnicode(text2);
                        stringBuilder.Append(text2);
                    }
                }
            }
        }

        return stringBuilder.ToString();
    }
}

0

Đây là giống hệt với câu trả lời được chấp nhận ngoại trừ nhỏ gọn hơn một chút:

private string ToQueryString(NameValueCollection nvc)
{
    return "?" + string.Join("&", nvc.AllKeys.Select(k => string.Format("{0}={1}", 
        HttpUtility.UrlEncode(k), 
        HttpUtility.UrlEncode(nvc[k]))));
}

0

Chỉ dành cho những người cần phiên bản VB.NET của câu trả lời hàng đầu:

Public Function ToQueryString(nvc As System.Collections.Specialized.NameValueCollection) As String
    Dim array As String() = nvc.AllKeys.SelectMany(Function(key As String) nvc.GetValues(key), Function(key As String, value As String) String.Format("{0}={1}", System.Web.HttpUtility.UrlEncode(key), System.Web.HttpUtility.UrlEncode(value))).ToArray()
    Return "?" + String.Join("&", array)
End Function

Và phiên bản không có LINQ:

Public Function ToQueryString(nvc As System.Collections.Specialized.NameValueCollection) As String
    Dim lsParams As New List(Of String)()

    For Each strKey As String In nvc.AllKeys
        Dim astrValue As String() = nvc.GetValues(strKey)

        For Each strValue As String In astrValue
            lsParams.Add(String.Format("{0}={1}", System.Web.HttpUtility.UrlEncode(strKey), System.Web.HttpUtility.UrlEncode(strValue)))
        Next ' Next strValue
    Next ' strKey
    Dim astrParams As String() = lsParams.ToArray()
    lsParams.Clear()
    lsParams = Nothing

    Return "?" + String.Join("&", astrParams)
End Function ' ToQueryString

Và phiên bản C # không có LINQ:

    public static string ToQueryString(System.Collections.Specialized.NameValueCollection nvc)
    {
        List<string> lsParams = new List<string>();

        foreach (string strKey in nvc.AllKeys)
        {
            string[] astrValue = nvc.GetValues(strKey);

            foreach (string strValue in astrValue)
            {
                lsParams.Add(string.Format("{0}={1}", System.Web.HttpUtility.UrlEncode(strKey), System.Web.HttpUtility.UrlEncode(strValue)));
            } // Next strValue

        } // Next strKey

        string[] astrParams =lsParams.ToArray();
        lsParams.Clear();
        lsParams = null;

        return "?" + string.Join("&", astrParams);
    } // End Function ToQueryString
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.