Bagaimana Anda UrlEncode tanpa menggunakan System.Web?

310

Saya mencoba untuk menulis aplikasi klien windows yang memanggil situs web untuk data. Untuk menjaga agar instalasi minimum, saya hanya mencoba menggunakan dll di Profil Klien .NET Framework . Masalahnya adalah saya perlu UrlEncode beberapa parameter, apakah ada cara mudah untuk melakukan ini tanpa mengimpor System.Web.dll yang bukan bagian dari Pofile Klien?

Martin Brown
sumber
Bisakah Anda menunjukkan bagaimana Anda melakukan panggilan ke situs web? Mungkin ada sesuatu yang bisa dilakukan di sana.
Darin Dimitrov
Karena penasaran, bagaimana Anda memanggil situs web untuk data tanpa menggunakan System.Web?
Patrick McDonald
@ Patrick, dia mungkin menggunakan WebRequestatau WebClient. Itulah alasan saya bertanya tentang kode khusus ini karena ada hal-hal yang dapat dilakukan tentang penyandian data url dengan benar.
Darin Dimitrov
1
Saya menggunakan objek System.Net.WebRequest. Lalu saya memanggil GetRequestStream dan menulis parameter Post saya ke stream. Saya juga mengatur ContentType ke "application / x-www-form-urlencoded".
Martin Brown
1
Tentu saja ini juga berlaku jika saya melakukan permintaan GET dan menambahkan parameter ke URL.
Martin Brown

Jawaban:

317

System.Uri.EscapeUriString() bisa bermasalah dengan karakter tertentu, bagi saya itu adalah tanda / pound '#' dalam string.

Jika itu masalah bagi Anda, cobalah:

System.Uri.EscapeDataString() //Works excellent with individual values

Berikut adalah jawaban pertanyaan SO yang menjelaskan perbedaannya:

Apa perbedaan antara EscapeUriString dan EscapeDataString?

dan merekomendasikan untuk digunakan Uri.EscapeDataString()dalam segala aspek.

ToddBFisher
sumber
1
Salah: blogs.msdn.com/b/yangxind/archive/2006/11/09/... Anda akan mengalami masalah dengan tanda plus karena tidak akan tidak disandi.
Chris Weber
7
Posting blog itu agak tua dan saya hanya memiliki "Uri Escaped" url penuh dan semua ruang telah menjadi% 20, jadi saya pikir mereka memperbaikinya. Saya menggunakan .Net 4.5.
Rodi
EscapeDataString juga tidak mendukung string yang sangat panjang jika Anda mempersiapkan data untuk operasi POST. stackoverflow.com/questions/6695208/…
Bron Davies
Uri.EscapeUriStringmemang sangat bermasalah dan tidak boleh digunakan, karena mencoba melakukan sesuatu (lolos URI penuh) yang sebenarnya tidak mungkin dilakukan secara konsisten. Lihat jawaban ini untuk penjelasan terperinci.
Livven
Juga karakter Space.
Waqas Shabbir
252

Dalam penggunaan .Net 4.5+ WebUtility

Hanya untuk memformat, saya mengirimkan ini sebagai jawaban.

Tidak dapat menemukan contoh bagus yang membandingkannya:

string testString = "http://test# space 123/text?var=val&another=two";
Console.WriteLine("UrlEncode:         " + System.Web.HttpUtility.UrlEncode(testString));
Console.WriteLine("EscapeUriString:   " + Uri.EscapeUriString(testString));
Console.WriteLine("EscapeDataString:  " + Uri.EscapeDataString(testString));
Console.WriteLine("EscapeDataReplace: " + Uri.EscapeDataString(testString).Replace("%20", "+"));

Console.WriteLine("HtmlEncode:        " + System.Web.HttpUtility.HtmlEncode(testString));
Console.WriteLine("UrlPathEncode:     " + System.Web.HttpUtility.UrlPathEncode(testString));

//.Net 4.0+
Console.WriteLine("WebUtility.HtmlEncode: " + WebUtility.HtmlEncode(testString));
//.Net 4.5+
Console.WriteLine("WebUtility.UrlEncode:  " + WebUtility.UrlEncode(testString));

Keluaran:

UrlEncode:             http%3a%2f%2ftest%23+space+123%2ftext%3fvar%3dval%26another%3dtwo
EscapeUriString:       http://test#%20space%20123/text?var=val&another=two
EscapeDataString:      http%3A%2F%2Ftest%23%20space%20123%2Ftext%3Fvar%3Dval%26another%3Dtwo
EscapeDataReplace:     http%3A%2F%2Ftest%23+space+123%2Ftext%3Fvar%3Dval%26another%3Dtwo

HtmlEncode:            http://test# space 123/text?var=val&another=two
UrlPathEncode:         http://test#%20space%20123/text?var=val&another=two

//.Net 4.0+
WebUtility.HtmlEncode: http://test# space 123/text?var=val&another=two
//.Net 4.5+
WebUtility.UrlEncode:  http%3A%2F%2Ftest%23+space+123%2Ftext%3Fvar%3Dval%26another%3Dtwo

Dalam penggunaan .Net 4.5+ WebUtility.UrlEncode

Ini tampaknya mereplikasi HttpUtility.UrlEncode(pra-v4.0) untuk karakter yang lebih umum:
Uri.EscapeDataString(testString).Replace("%20", "+").Replace("'", "%27").Replace("~", "%7E")
Catatan: EscapeUriStringakan menyimpan string uri yang valid, yang menyebabkannya menggunakan sebanyak mungkin karakter plaintext.

Lihat jawaban ini untuk Tabel yang Membandingkan berbagai Pengodean:
https://stackoverflow.com/a/11236038/555798

Line Breaks Semuanya terdaftar di sini (selain HttpUtility.HtmlEncode) akan dikonversi "\n\r"menjadi %0a%0datau%0A%0D

Silakan mengedit ini dan menambahkan karakter baru ke string pengujian saya, atau biarkan di komentar dan saya akan mengeditnya.

Timin
sumber
Dalam kasus saya, saya harus menggunakan EscapeDataStringdaripada EscapeUriStringsaat kami menyandikan carriage return dan line feeds dan ini membutuhkan pelarian yang lebih agresif yang dilakukan olehEscapeDataString
David O'Meara
1
lebih banyak contoh, Anda dapat memberikan kasus uji sendiri jika diinginkan. Berikut adalah contoh menjalankannya dan metode penyandian lain yang menunjukkan perbedaan dotnetfiddle.net/12IFw1
Maslow
3
WebUtility.UrlEncode () dan WebUtility.UrlDecode () adalah 4,5+. Mereka tidak ada di 4.0.
Derek Kalweit
The msdn mengatakan: "Universal Windows Platform: Tersedia sejak 4,5, .NET Framework: Tersedia sejak 4.0" ...
Thymine
54

Kamu bisa memakai

Uri.EscapeUriString (lihat http://msdn.microsoft.com/en-us/library/system.uri.escapeuristring.aspx )

Matthew Manela
sumber
Apakah ada perbedaan antara ini dan EscapeDataString?
Martin Brown
3
Anda ingin menggunakan EscapeUriString. EscapeUriString akan mencoba untuk menyandikan seluruh url (termasuk http: // bagian) sementara EscapeUriString memahami bagian mana yang sebenarnya harus dikodekan
Matthew Manela
1
Begitu, jadi dalam contoh ini saya mungkin ingin EscapeDataString karena saya mungkin ingin meneruskan URL sebagai parameter get. Saya menambahkan ke URL dalam hal ini.
Martin Brown
5
@MatthewManela Saya cukup yakin komentar Oct1 Anda harus membaca The EscapeDataString akan mencoba untuk menyandikan ...
Maslow
Jangan gunakan Uri.EscapeUriString. Itu tidak "memahami" bagian mana yang harus dikodekan, itu hanya upaya sesat dalam melakukan sesuatu (melarikan diri URI penuh) yang sebenarnya tidak mungkin dilakukan secara konsisten. Lihat jawaban ini untuk penjelasan terperinci.
Livven
20

Jawabannya di sini sangat bagus, tetapi masih kurang bagi saya.

Saya menulis loop kecil yang membandingkan Uri.EscapeUriStringdengan Uri.EscapeDataStringuntuk semua karakter dari 0 hingga 255.

CATATAN: Kedua fungsi memiliki kecerdasan bawaan bahwa karakter di atas 0x80 pertama kali dikodekan UTF-8 dan kemudian dikodekan persen.

Inilah hasilnya:

******* Different *******

'#' -> Uri "#" Data "%23"
'$' -> Uri "$" Data "%24"
'&' -> Uri "&" Data "%26"
'+' -> Uri "+" Data "%2B"
',' -> Uri "," Data "%2C"
'/' -> Uri "/" Data "%2F"
':' -> Uri ":" Data "%3A"
';' -> Uri ";" Data "%3B"
'=' -> Uri "=" Data "%3D"
'?' -> Uri "?" Data "%3F"
'@' -> Uri "@" Data "%40"


******* Not escaped *******

'!' -> Uri "!" Data "!"
''' -> Uri "'" Data "'"
'(' -> Uri "(" Data "("
')' -> Uri ")" Data ")"
'*' -> Uri "*" Data "*"
'-' -> Uri "-" Data "-"
'.' -> Uri "." Data "."
'_' -> Uri "_" Data "_"
'~' -> Uri "~" Data "~"

'0' -> Uri "0" Data "0"
.....
'9' -> Uri "9" Data "9"

'A' -> Uri "A" Data "A"
......
'Z' -> Uri "Z" Data "Z"

'a' -> Uri "a" Data "a"
.....
'z' -> Uri "z" Data "z"

******* UTF 8 *******

.....
'Ò' -> Uri "%C3%92" Data "%C3%92"
'Ó' -> Uri "%C3%93" Data "%C3%93"
'Ô' -> Uri "%C3%94" Data "%C3%94"
'Õ' -> Uri "%C3%95" Data "%C3%95"
'Ö' -> Uri "%C3%96" Data "%C3%96"
.....

EscapeUriStringdigunakan untuk menyandikan URL, sedangkan EscapeDataStringuntuk menyandikan misalnya konten Cookie, karena data Cookie tidak boleh berisi karakter yang dilindungi undang-undang '='dan ';'.

Elmue
sumber
analisis dan pemecahan yang bagus di sini, sangat membantu. jika ada yang memiliki atau mengetahui tolok ukur kinerja (membandingkan ketiga metode) yang juga menyenangkan untuk dilihat
Shaun Wilson
Ini adalah analisis yang baik dan kesimpulannya adalah Anda tidak boleh menggunakannya Uri.EscapeUriString, karena melarikan diri dari URI penuh tidak mungkin dilakukan secara konsisten. Lihat jawaban ini untuk penjelasan terperinci.
Livven
16

Ada versi yang dapat digunakan profil klien, kelas System.Net.WebUtility, hadir di profil klien System.dll. Inilah Tautan MSDN:

WebUtilitas

Sprague
sumber
Saya perhatikan bahwa halaman bantuan untuk kelas itu secara khusus mengatakan "Menyediakan metode untuk menyandikan dan mendekode URL ketika memproses permintaan Web." jadi mungkin saja mereka tidak menyebutkan metode dengan baik.
James White
Poin bagus, katakanlah, mengapa Anda tidak memilih saudara laki-laki;) suara turun ini telah menghantui saya selama 2 tahun! JK ... tapi jujur ​​itu mungkin mengapa saya memposting tautan itu, sialnya saya terkena pukulan reputasi karena kesalahan dalam dokumen Microsoft ...
Sprague
11
Sepertinya UrlEncode dan UrlDecode hanya ditambahkan ke WebUtility di versi 4.5 .Net.
Martin Brown
8

Berikut adalah contoh pengiriman permintaan POST yang menyandikan parameter dengan benar menggunakan application/x-www-form-urlencodedtipe konten:

using (var client = new WebClient())
{
    var values = new NameValueCollection
    {
        { "param1", "value1" },
        { "param2", "value2" },
    };
    var result = client.UploadValues("http://foo.com", values);
}
Darin Dimitrov
sumber
-3
System.Net.WebUtility.HtmlDecode
pengguna3105093
sumber
Kelas WebUtility menyediakan metode untuk encoding dan decoding URL saat memproses permintaan Web. Itu melakukan hal yang sama seperti HttpUtility tapi itu keluar dari namespace System.Web
Alexandru Aliu
3
Itu salah karena HtmlDecodes dan tidak UrlEncode seperti pertanyaan yang diajukan. Bahkan HtmlEncode akan salah karena penyandian HTML berbeda dengan penyandian URL.
Martin Brown