TL; DR: kabul edilen sürümü kullanmayın, çünkü unicode karakterlerin işlenmesiyle tamamen kırılmıştır ve asla dahili API kullanmaz
Aslında kabul edilen çözümle garip çift kodlama sorunu buldum:
Dolayısıyla, kodlanması gereken karakterlerle uğraşıyorsanız, kabul edilen çözüm çift kodlamaya yol açar:
- sorgu parametreleri
NameValueCollection
indeksleyici kullanılarak otomatik olarak kodlanır ( ve bu kullanım UrlEncodeUnicode
, normal beklenen değil UrlEncode
(!) )
- Ardından, bir kez daha kodlama yapan bir yapıcı kullanarak
uriBuilder.Uri
yeni oluştururUri
(normal url kodlaması)
- Bunu yaparak
uriBuilder.ToString()
(bu, Uri
IMO'nun en azından tutarsızlık, belki bir hata, ancak bu başka bir soru olduğu doğru döndürülse de) ve ardından HttpClient
dize kabul eden yöntemi kullanarak - istemci yine Uri
de şu şekilde geçirilen dizeden oluşturur :new Uri(uri, UriKind.RelativeOrAbsolute)
Küçük ama tam repro:
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!
Çıktı:
?cyrillic=%u043a%u0438%u0440%u0438%u043b%u0438%u0446%u044f
https://127.0.0.1/app?cyrillic=%25u043a%25u0438%25u0440%25u0438%25u043b%25u0438%25u0446%25u044f
Gördüğünüz gibi, uribuilder.ToString()
+ httpClient.GetStringAsync(string)
veya uriBuilder.Uri
+ yaparsanız yapınhttpClient.GetStringAsync(Uri)
yaparsanız yapın, çift kodlanmış parametre gönderirsiniz
Sabit örnek şunlar olabilir:
var uri = new Uri(builder.ToString(), dontEscape: true);
new HttpClient().GetStringAsync(uri);
Ama bu kullanır eskimiş Uri
yapıcısı
PS, Windows Server'daki en son Uri
.NET'imde, bool doc yorumuna sahip yapıcı "eski, dontEscape her zaman yanlıştır" diyor, ancak aslında beklendiği gibi çalışıyor (kaçıyor)
Yani başka bir hata gibi görünüyor ...
Ve bu bile yanlıştır - UrlEncodedUnicode'u sunucuya gönderir, sadece UrlEncoded sunucunun beklediği gibi değil
Güncelleme: bir şey daha var, NameValueCollection aslında artık kullanılmaması gereken ve normal url.encode / decode ile uyumsuz olan UrlEncodeUnicode yapıyor (bkz . URL Sorgusu için NameValueCollection? ).
İşin özü Yani: Bu kesmek kullanmak aslaNameValueCollection query = HttpUtility.ParseQueryString(builder.Query);
sizin unicode sorgu parametreleri karmaşa olacak şekilde. Sorguyu manuel olarak derleyin ve UriBuilder.Query
gerekli kodlamayı yapacak olan atamayı yapın ve ardından Uri'yi kullanın UriBuilder.Uri
.
Bunun gibi kullanılması gerekmeyen kodu kullanarak kendinizi incitmenin ana örneği