สร้างสตริงแบบสอบถามสำหรับ System.Net.HttpClient get


184

หากฉันต้องการส่งคำขอการรับ http โดยใช้ System.Net.HttpClient ดูเหมือนว่าไม่มี API ที่จะเพิ่มพารามิเตอร์การแก้ไขนี้ถูกต้องหรือไม่

มี api ง่าย ๆ ในการสร้างสตริงการสืบค้นที่ไม่เกี่ยวข้องกับการสร้างคอลเลกชันค่าชื่อและการเข้ารหัส url เหล่านั้นและจากนั้นก็เชื่อมต่อพวกเขาในที่สุด? ฉันหวังว่าจะใช้สิ่งที่ต้องการ API ของ RestSharp (เช่น AddParameter (.. ))


@Michael Perrenoud คุณอาจต้องการพิจารณาอีกครั้งโดยใช้คำตอบที่ยอมรับพร้อมอักขระที่ต้องเข้ารหัสดูคำอธิบายของฉันด้านล่าง
ผู้อพยพผิดกฎหมาย

คำตอบ:


309

หากฉันต้องการส่งคำขอการรับ http โดยใช้ System.Net.HttpClient ดูเหมือนว่าไม่มี API ที่จะเพิ่มพารามิเตอร์การแก้ไขนี้ถูกต้องหรือไม่

ใช่.

มี api ง่าย ๆ ในการสร้างสตริงการสืบค้นที่ไม่เกี่ยวข้องกับการสร้างคอลเลกชันค่าชื่อและการเข้ารหัส url เหล่านั้นและจากนั้นก็เชื่อมต่อพวกเขาในที่สุด?

แน่นอนว่า:

var query = HttpUtility.ParseQueryString(string.Empty);
query["foo"] = "bar<>&-baz";
query["bar"] = "bazinga";
string queryString = query.ToString();

จะให้ผลลัพธ์ที่คาดหวังแก่คุณ:

foo=bar%3c%3e%26-baz&bar=bazinga

คุณอาจพบว่าUriBuilderคลาสมีประโยชน์:

var builder = new UriBuilder("http://example.com");
builder.Port = -1;
var query = HttpUtility.ParseQueryString(builder.Query);
query["foo"] = "bar<>&-baz";
query["bar"] = "bazinga";
builder.Query = query.ToString();
string url = builder.ToString();

จะให้ผลลัพธ์ที่คาดหวังแก่คุณ:

http://example.com/?foo=bar%3c%3e%26-baz&bar=bazinga

ที่คุณสามารถทำได้อย่างปลอดภัยมากกว่าHttpClient.GetAsyncวิธีการของคุณ


9
นั่นเป็นสิ่งที่ดีที่สุดในแง่ของการจัดการ URL ใน. NET ไม่จำเป็นต้องมีการเข้ารหัส url ด้วยตนเองและทำการเชื่อมต่อสตริงหรือผู้สร้างสตริงหรืออะไรก็ตาม คลาส UriBuilder จะจัดการ URL ที่มีแฟรกเมนต์ ( #) ให้กับคุณโดยใช้คุณสมบัติ Fragment ฉันเห็นคนจำนวนมากทำผิดพลาดในการจัดการ URL ด้วยตนเองแทนที่จะใช้เครื่องมือในตัว
ดารินทร์ดิมิทรอฟ

6
NameValueCollection.ToString()ตามปกติแล้วจะไม่สร้างสตริงการสืบค้นและไม่มีเอกสารที่ระบุว่าการทำToStringตามผลลัพธ์ParseQueryStringจะส่งผลให้เกิดสตริงการสืบค้นใหม่ซึ่งอาจแตกได้ตลอดเวลาเนื่องจากไม่มีการรับประกันในการทำงาน
แมทธิว

11
HttpUtility อยู่ใน System.Web ซึ่งไม่สามารถใช้ได้กับรันไทม์แบบพกพา ดูเหมือนว่าแปลกที่ฟังก์ชั่นนี้ไม่สามารถใช้ได้ในไลบรารีคลาส
Chris Eldredge

82
โซลูชันนี้น่ารังเกียจ . Net ควรมีตัวสร้างการสืบค้นที่เหมาะสม
Kugel

8
ความจริงที่ว่าทางออกที่ดีที่สุดนั้นถูกซ่อนอยู่ในคลาสภายในซึ่งคุณจะได้รับจากการเรียกใช้วิธีการยูทิลิตี้ที่ส่งผ่านสตริงว่างเปล่าเท่านั้นไม่สามารถเรียกได้ว่าเป็นโซลูชันที่สวยงาม
Kugel

79

สำหรับผู้ที่ไม่ต้องการรวมSystem.Webไว้ในโครงการที่ยังไม่ได้ใช้คุณสามารถใช้FormUrlEncodedContentจากSystem.Net.Httpและทำสิ่งต่อไปนี้:

รุ่น keyvaluepair

string query;
using(var content = new FormUrlEncodedContent(new KeyValuePair<string, string>[]{
    new KeyValuePair<string, string>("ham", "Glazed?"),
    new KeyValuePair<string, string>("x-men", "Wolverine + Logan"),
    new KeyValuePair<string, string>("Time", DateTime.UtcNow.ToString()),
})) {
    query = content.ReadAsStringAsync().Result;
}

เวอร์ชันพจนานุกรม

string query;
using(var content = new FormUrlEncodedContent(new Dictionary<string, string>()
{
    { "ham", "Glaced?"},
    { "x-men", "Wolverine + Logan"},
    { "Time", DateTime.UtcNow.ToString() },
})) {
    query = content.ReadAsStringAsync().Result;
}

ทำไมคุณใช้คำสั่งที่ใช้?
Ian Warburton

มีแนวโน้มที่จะเพิ่มทรัพยากร แต่เป็นสิ่งที่เกินความจำเป็น อย่าทำอย่างนี้
ดี้

5
สิ่งนี้สามารถกระชับได้มากกว่าโดยใช้ Dictionary <string, string> แทนที่จะเป็นอาร์เรย์ KVP จากนั้นใช้ไวยากรณ์เริ่มต้นของ: {"แฮม", "Glazed?" }
Sean B

@SeanB เป็นความคิดที่ดีโดยเฉพาะอย่างยิ่งเมื่อใช้บางอย่างเพื่อเพิ่มรายการพารามิเตอร์แบบไดนามิก / ไม่รู้จัก สำหรับตัวอย่างนี้เนื่องจากเป็นรายการ "คงที่" ฉันไม่รู้สึกว่าค่าใช้จ่ายของพจนานุกรมคุ้มค่า
Rostov

6
@Kody ทำไมคุณถึงบอกว่าอย่าใช้dispose? ฉันมักจะทิ้งถ้าฉันมีเหตุผลที่ดีที่จะไม่เหมือน HttpClientreusing
Dan Friedman

41

TL; DR: อย่าใช้เวอร์ชันที่ยอมรับเนื่องจากใช้งานไม่ได้กับการจัดการอักขระ unicode และไม่ใช้ API ภายใน

ฉันพบปัญหาการเข้ารหัสสองครั้งที่แปลกจริง ๆ ด้วยวิธีการแก้ปัญหาที่ยอมรับ:

ดังนั้นหากคุณกำลังจัดการกับตัวละครที่จะต้องมีการเข้ารหัสโซลูชั่นที่ได้รับการยอมรับจะนำไปสู่การเข้ารหัสซ้ำ:

  • พารามิเตอร์การสืบค้นจะถูกเข้ารหัสอัตโนมัติโดยใช้NameValueCollectionตัวจัดทำดัชนี ( และการใช้นี้UrlEncodeUnicodeไม่ได้คาดหวังอย่างสม่ำเสมอUrlEncode(!) )
  • จากนั้นเมื่อคุณเรียกuriBuilder.Uriมันสร้างใหม่Uriโดยใช้ตัวสร้างซึ่งจะเข้ารหัสอีกครั้ง (การเข้ารหัส URL ปกติ)
  • ที่ไม่สามารถหลีกเลี่ยงได้โดยการทำuriBuilder.ToString() (แม้ว่าผลตอบแทนจะถูกต้องUriซึ่ง IMO นั้นไม่สอดคล้องกันอย่างน้อยอาจเป็นข้อผิดพลาด แต่เป็นคำถามอื่น) แล้วใช้HttpClientวิธีการยอมรับสตริง - ไคลเอนต์ยังคงสร้างUriสตริงที่ส่งผ่านของคุณดังนี้new Uri(uri, UriKind.RelativeOrAbsolute)

ขนาดเล็ก แต่เต็มไปด้วยความนิยม:

var builder = new UriBuilder
{
    Scheme = Uri.UriSchemeHttps,
    Port = -1,
    Host = "127.0.0.1",
    Path = "app"
};

NameValueCollection query = HttpUtility.ParseQueryString(builder.Query);

query["cyrillic"] = "кирилиця";

builder.Query = query.ToString();
Console.WriteLine(builder.Query); //query with cyrillic stuff UrlEncodedUnicode, and that's not what you want

var uri = builder.Uri; // creates new Uri using constructor which does encode and messes cyrillic parameter even more
Console.WriteLine(uri);

// this is still wrong:
var stringUri = builder.ToString(); // returns more 'correct' (still `UrlEncodedUnicode`, but at least once, not twice)
new HttpClient().GetStringAsync(stringUri); // this creates Uri object out of 'stringUri' so we still end up sending double encoded cyrillic text to server. Ouch!

เอาท์พุท:

?cyrillic=%u043a%u0438%u0440%u0438%u043b%u0438%u0446%u044f

https://127.0.0.1/app?cyrillic=%25u043a%25u0438%25u0440%25u0438%25u043b%25u0438%25u0446%25u044f

ดังที่คุณเห็นไม่ว่าคุณจะuribuilder.ToString()+ httpClient.GetStringAsync(string)หรือuriBuilder.Uri+ httpClient.GetStringAsync(Uri)คุณจะสิ้นสุดการส่งพารามิเตอร์ที่เข้ารหัสสองครั้ง

ตัวอย่างคงที่อาจเป็น:

var uri = new Uri(builder.ToString(), dontEscape: true);
new HttpClient().GetStringAsync(uri);

แต่สิ่งนี้ใช้ตัวสร้างที่ล้าสมัย Uri

PS บน. NET ล่าสุดของฉันบน Windows Server คอนUriสตรัคเตอร์ที่มีความคิดเห็น bool doc บอกว่า "ล้าสมัย dontEscape เป็นเท็จเสมอ" แต่ใช้งานได้จริงตามที่คาดไว้ (ข้ามการหลบหนี)

ดังนั้นดูเหมือนว่าข้อผิดพลาดอื่น ...

และแม้กระทั่งสิ่งนี้ผิดธรรมดา - มันส่ง UrlEncodedUnicode ไปยังเซิร์ฟเวอร์ไม่ใช่แค่ UrlEncoded สิ่งที่เซิร์ฟเวอร์คาดหวัง

อัปเดต: อีกสิ่งหนึ่งคือ NameValueCollection จริง ๆ แล้ว UrlEncodeUnicode ซึ่งไม่ควรใช้อีกต่อไปและเข้ากันไม่ได้กับ url.encode / ถอดรหัสปกติ (ดูที่NameValueCollection กับ URL Query )

ดังนั้นบรรทัดล่างคือ: อย่าใช้แฮ็คนี้NameValueCollection query = HttpUtility.ParseQueryString(builder.Query);เพราะมันจะทำให้พารามิเตอร์การสืบค้นยูนิโค้ดของคุณยุ่งเหยิง เพียงแค่สร้างแบบสอบถามด้วยตนเองและกำหนดให้UriBuilder.Queryซึ่งจะทำการเข้ารหัสที่จำเป็นและจากนั้นได้รับ Uri UriBuilder.Uriใช้

ตัวอย่างที่เด่นชัดของการทำร้ายตัวเองโดยใช้รหัสซึ่งไม่ควรใช้เช่นนี้


16
คุณสามารถเพิ่มฟังก์ชั่นยูทิลิตี้ที่สมบูรณ์ให้กับคำตอบนี้ได้ไหม
mafu

8
ฉันสอง mafu ในนี้: ฉันอ่านคำตอบ แต่ไม่มีข้อสรุป มีคำตอบที่ชัดเจนสำหรับเรื่องนี้หรือไม่?
Richard Griffiths

3
ฉันต้องการเห็นคำตอบที่ชัดเจนสำหรับปัญหานี้ด้วย
Pones

คำตอบที่ชัดเจนสำหรับปัญหานี้คือการใช้var namedValues = HttpUtility.ParseQueryString(builder.Query)แต่แล้วแทนที่จะใช้ NameValueCollection ที่ส่งคืนให้แปลงเป็นพจนานุกรมทันทีเช่น: var dic = values.ToDictionary(x => x, x => values[x]); เพิ่มค่าใหม่ให้กับพจนานุกรมจากนั้นส่งต่อไปยังตัวสร้างFormUrlEncodedContentและเรียกReadAsStringAsync().Resultใช้ ซึ่งให้สตริงการสืบค้นที่เข้ารหัสอย่างถูกต้องซึ่งคุณสามารถกำหนดกลับไปที่ UriBuilder
Triynko

จริงๆคุณสามารถเพียงแค่ใช้ NamedValueCollection.ToString แทนของทุกสิ่งที่ แต่ถ้าคุณเปลี่ยน app.config / web.config การตั้งค่าที่ป้องกันไม่ให้ ASP.NET จากการใช้ '% uXXXX' <add key="aspnet:DontUsePercentUUrlEncoding" value="true" />เข้ารหัส: ฉันจะไม่ขึ้นอยู่กับพฤติกรรมนี้ดังนั้นจึงเป็นการดีกว่าที่จะใช้คลาส FormUrlEncodedContent ดังที่แสดงโดยคำตอบก่อนหน้านี้: stackoverflow.com/a/26744471/88409
Triynko

41

ในโครงการ ASP.NET Core คุณสามารถใช้คลาส QueryHelpers

// using Microsoft.AspNetCore.WebUtilities;
var query = new Dictionary<string, string>
{
    ["foo"] = "bar",
    ["foo2"] = "bar2",
    // ...
};

var response = await client.GetAsync(QueryHelpers.AddQueryString("/api/", query));

2
มันน่ารำคาญที่แม้ว่าในกระบวนการนี้คุณยังไม่สามารถส่งค่าหลายค่าสำหรับคีย์เดียวกันได้ หากคุณต้องการส่ง "บาร์" และ "บาร์ 2" เป็นส่วนหนึ่งของเพียงแค่ foo มันเป็นไปไม่ได้
m0g

2
นี่เป็นคำตอบที่ยอดเยี่ยมสำหรับแอพที่ทันสมัยทำงานในสถานการณ์ของฉันง่ายและสะอาด อย่างไรก็ตามฉันไม่ต้องการกลไกการหลบหนีใด ๆ - ไม่ได้ทดสอบ
Patrick Stalph

แพคเกจ NuGet นี้มีเป้าหมายที่. NET 2.0 มาตรฐานซึ่งหมายความว่าคุณสามารถใช้งานได้บน. NET Framework แบบเต็ม 4.6.1+
eddiewould

24

คุณอาจต้องการที่จะตรวจสอบFlurl [เปิดเผย: ฉันเป็นผู้เขียน], เครื่องมือสร้าง URL ที่คล่องแคล่วพร้อมกับสหายที่ไม่จำเป็นซึ่งขยายเข้าไปในไคลเอนต์ REST ที่เต็มไปด้วยเสียง

var result = await "https://api.com"
    // basic URL building:
    .AppendPathSegment("endpoint")
    .SetQueryParams(new {
        api_key = ConfigurationManager.AppSettings["SomeApiKey"],
        max_results = 20,
        q = "Don't worry, I'll get encoded!"
    })
    .SetQueryParams(myDictionary)
    .SetQueryParam("q", "overwrite q!")

    // extensions provided by Flurl.Http:
    .WithOAuthBearerToken("token")
    .GetJsonAsync<TResult>();

ตรวจสอบเอกสารสำหรับรายละเอียดเพิ่มเติม แพคเกจเต็มมีอยู่ใน NuGet:

PM> Install-Package Flurl.Http

หรือตัวสร้าง URL แบบสแตนด์อะโลน:

PM> Install-Package Flurl


2
ทำไมไม่ขยายUriหรือเริ่มต้นกับการเรียนของคุณเองแทนที่จะstring?
mpen

2
เทคนิคผมไม่เริ่มต้นด้วยตัวฉันเองUrlระดับ ด้านบนเทียบเท่ากับnew Url("https://api.com").AppendPathSegment...ส่วนตัวฉันชอบส่วนขยายของสตริงเนื่องจากการกดแป้นน้อยลงและได้มาตรฐานบนเอกสารในเอกสาร แต่คุณสามารถทำได้ทั้งสองวิธี
Todd Menier

ปิดหัวข้อ แต่ lib ที่ดีจริงๆฉันใช้มันหลังจากได้เห็นสิ่งนี้ ขอบคุณที่ใช้ IHttpClientFactory เช่นกัน
Ed S.

4

ในบรรทัดเดียวกับโพสต์ของ Rostov หากคุณไม่ต้องการรวมการอ้างอิงถึงSystem.Webในโครงการของคุณคุณสามารถใช้FormDataCollectionจากSystem.Net.Http.Formattingและทำสิ่งต่อไปนี้:

การใช้ System.Net.Http.Formatting.FormDataCollection

var parameters = new Dictionary<string, string>()
{
    { "ham", "Glaced?" },
    { "x-men", "Wolverine + Logan" },
    { "Time", DateTime.UtcNow.ToString() },
}; 
var query = new FormDataCollection(parameters).ReadAsNameValueCollection().ToString();

3

ดารินนำเสนอทางออกที่น่าสนใจและชาญฉลาดและนี่คือสิ่งที่อาจเป็นตัวเลือกอื่น:

public class ParameterCollection
{
    private Dictionary<string, string> _parms = new Dictionary<string, string>();

    public void Add(string key, string val)
    {
        if (_parms.ContainsKey(key))
        {
            throw new InvalidOperationException(string.Format("The key {0} already exists.", key));
        }
        _parms.Add(key, val);
    }

    public override string ToString()
    {
        var server = HttpContext.Current.Server;
        var sb = new StringBuilder();
        foreach (var kvp in _parms)
        {
            if (sb.Length > 0) { sb.Append("&"); }
            sb.AppendFormat("{0}={1}",
                server.UrlEncode(kvp.Key),
                server.UrlEncode(kvp.Value));
        }
        return sb.ToString();
    }
}

และเมื่อใช้งานคุณอาจทำสิ่งนี้:

var parms = new ParameterCollection();
parms.Add("key", "value");

var url = ...
url += "?" + parms;

5
คุณต้องการเข้ารหัสkvp.Keyและkvp.Valueแยกต่างหากภายใน for for loop ไม่ใช่ใน full query-string (ดังนั้นจึงไม่เข้ารหัส&และ=อักขระ)
แมทธิว

ขอบคุณไมค์ โซลูชันที่เสนออื่น ๆ (ที่เกี่ยวข้องกับ NameValueCollection) ไม่ทำงานสำหรับฉันเพราะฉันอยู่ในโครงการ PCL ดังนั้นนี่จึงเป็นทางเลือกที่สมบูรณ์แบบ สำหรับคนอื่น ๆ ที่กำลังทำงานด้านลูกค้าserver.UrlEncodeสามารถแทนที่ด้วยWebUtility.UrlEncode
BCA

2

หรือเพียงแค่ใช้ส่วนขยาย Uri ของฉัน

รหัส

public static Uri AttachParameters(this Uri uri, NameValueCollection parameters)
{
    var stringBuilder = new StringBuilder();
    string str = "?";
    for (int index = 0; index < parameters.Count; ++index)
    {
        stringBuilder.Append(str + parameters.AllKeys[index] + "=" + parameters[index]);
        str = "&";
    }
    return new Uri(uri + stringBuilder.ToString());
}

การใช้

Uri uri = new Uri("http://www.example.com/index.php").AttachParameters(new NameValueCollection
                                                                           {
                                                                               {"Bill", "Gates"},
                                                                               {"Steve", "Jobs"}
                                                                           });

ผลลัพธ์

http://www.example.com/index.php?Bill=Gates&Steve=Jobs


27
คุณไม่ลืมการเข้ารหัส URL ใช่ไหม
Kugel

1
นี่เป็นตัวอย่างที่ดีของการใช้ส่วนขยายเพื่อสร้างผู้ช่วยเหลือที่ชัดเจนและมีประโยชน์ หากคุณรวมสิ่งนี้กับคำตอบที่ได้รับการยอมรับคุณกำลังจะสร้าง RestClient ที่มั่นคง
emran

2

RFC 6570 URI แม่แบบห้องสมุดฉันกำลังพัฒนาที่มีความสามารถในการดำเนินการดำเนินการนี้ การเข้ารหัสทั้งหมดได้รับการจัดการให้กับคุณตาม RFC นั้น ในขณะที่เขียนนี้มีรุ่นเบต้าและเหตุผลเดียวที่ไม่ถือว่าเป็นรุ่น 1.0 ที่มีความเสถียรคือเอกสารไม่ตอบสนองความต้องการของฉันได้อย่างเต็มที่ (ดูปัญหาที่# 17 , # 18 , # 32 , # 43 )

คุณสามารถสร้างสตริงแบบสอบถามอย่างเดียว:

UriTemplate template = new UriTemplate("{?params*}");
var parameters = new Dictionary<string, string>
  {
    { "param1", "value1" },
    { "param2", "value2" },
  };
Uri relativeUri = template.BindByName(parameters);

หรือคุณสามารถสร้าง URI แบบสมบูรณ์:

UriTemplate template = new UriTemplate("path/to/item{?params*}");
var parameters = new Dictionary<string, string>
  {
    { "param1", "value1" },
    { "param2", "value2" },
  };
Uri baseAddress = new Uri("http://www.example.com");
Uri relativeUri = template.BindByName(baseAddress, parameters);

1

เนื่องจากฉันต้องนำมาใช้ซ้ำในเวลานี้ฉันจึงมากับคลาสนี้ที่ช่วยสรุปนามธรรมว่าสตริงข้อความค้นหาประกอบด้วยอะไร

public class UriBuilderExt
{
    private NameValueCollection collection;
    private UriBuilder builder;

    public UriBuilderExt(string uri)
    {
        builder = new UriBuilder(uri);
        collection = System.Web.HttpUtility.ParseQueryString(string.Empty);
    }

    public void AddParameter(string key, string value) {
        collection.Add(key, value);
    }

    public Uri Uri{
        get
        {
            builder.Query = collection.ToString();
            return builder.Uri;
        }
    }

}

การใช้จะลดความซับซ้อนลงในบางสิ่งเช่นนี้:

var builder = new UriBuilderExt("http://example.com/");
builder.AddParameter("foo", "bar<>&-baz");
builder.AddParameter("bar", "second");
var uri = builder.Uri;

ที่จะส่งคืน uri: http://example.com/?foo=bar%3c%3e%26-baz&bar=second


1

เพื่อหลีกเลี่ยงปัญหาการเข้ารหัสสองครั้งที่อธิบายไว้ในคำตอบ taras.roshko และเพื่อให้เป็นไปได้ในการทำงานได้อย่างง่ายดายด้วยพารามิเตอร์การค้นหาคุณสามารถใช้แทนuriBuilder.Uri.ParseQueryString()HttpUtility.ParseQueryString()


1

ส่วนที่ดีของคำตอบที่ยอมรับแก้ไขเพื่อใช้ UriBuilder.Uri.ParseQueryString () แทน HttpUtility.ParseQueryString ():

var builder = new UriBuilder("http://example.com");
var query = builder.Uri.ParseQueryString();
query["foo"] = "bar<>&-baz";
query["bar"] = "bazinga";
builder.Query = query.ToString();
string url = builder.ToString();

FYI: เรื่องนี้ต้องมีการอ้างอิงถึงSystem.Net.Httpเป็นวิธีขยายไม่ได้อยู่ในParseQueryString() System
Sunny Patel

0

ขอบคุณ "Darin Dimitrov" นี่คือวิธีการขยาย

 public static partial class Ext
{
    public static Uri GetUriWithparameters(this Uri uri,Dictionary<string,string> queryParams = null,int port = -1)
    {
        var builder = new UriBuilder(uri);
        builder.Port = port;
        if(null != queryParams && 0 < queryParams.Count)
        {
            var query = HttpUtility.ParseQueryString(builder.Query);
            foreach(var item in queryParams)
            {
                query[item.Key] = item.Value;
            }
            builder.Query = query.ToString();
        }
        return builder.Uri;
    }

    public static string GetUriWithparameters(string uri,Dictionary<string,string> queryParams = null,int port = -1)
    {
        var builder = new UriBuilder(uri);
        builder.Port = port;
        if(null != queryParams && 0 < queryParams.Count)
        {
            var query = HttpUtility.ParseQueryString(builder.Query);
            foreach(var item in queryParams)
            {
                query[item.Key] = item.Value;
            }
            builder.Query = query.ToString();
        }
        return builder.Uri.ToString();
    }
}

-1

ฉันไม่พบวิธีแก้ปัญหาที่ดีไปกว่าการสร้างวิธีการขยายการแปลงพจนานุกรมเป็น QueryStringFormat โซลูชันที่เสนอโดย Waleed AK นั้นดีเช่นกัน

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

สร้างวิธีการขยาย:

public static class DictionaryExt
{
    public static string ToQueryString<TKey, TValue>(this Dictionary<TKey, TValue> dictionary)
    {
        return ToQueryString<TKey, TValue>(dictionary, "?");
    }

    public static string ToQueryString<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, string startupDelimiter)
    {
        string result = string.Empty;
        foreach (var item in dictionary)
        {
            if (string.IsNullOrEmpty(result))
                result += startupDelimiter; // "?";
            else
                result += "&";

            result += string.Format("{0}={1}", item.Key, item.Value);
        }
        return result;
    }
}

และพวกเขา:

var param = new Dictionary<string, string>
          {
            { "param1", "value1" },
            { "param2", "value2" },
          };
param.ToQueryString(); //By default will add (?) question mark at begining
//"?param1=value1&param2=value2"
param.ToQueryString("&"); //Will add (&)
//"&param1=value1&param2=value2"
param.ToQueryString(""); //Won't add anything
//"param1=value1&param2=value2"

1
โซลูชันนี้ไม่มีการเข้ารหัส URL ที่ถูกต้องของพารามิเตอร์และจะไม่ทำงานกับค่าที่มีอักขระ 'ไม่ถูกต้อง'
Xavier Poinas

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