Server.UrlEncode vs. HttpUtility.UrlEncode

177

Apakah ada perbedaan antara Server.UrlEncode dan HttpUtility.UrlEncode?

Manu
sumber

Jawaban:

133

HttpServerUtility.UrlEncodeakan digunakan secara HttpUtility.UrlEncodeinternal. Tidak ada perbedaan khusus. Alasan adanya Server.UrlEncodekompatibilitas dengan ASP klasik.

Mehrdad Afshari
sumber
3
Adapun apa yang lolos. Secara internal ia menyebut fungsi ini referenceource.microsoft.com/#System/net/System/Net/…
Jeff
Untuk pembaca: Silakan lihat jawaban Joel Muller di bawah ini. Itu adalah cara paling efektif untuk menyandikan URL: stackoverflow.com/a/603962/190476
Sudhanshu Mishra
264

Saya mengalami sakit kepala yang signifikan dengan metode-metode ini sebelumnya, saya sarankan Anda menghindari varian apa pun UrlEncode, dan alih-alih menggunakanUri.EscapeDataString - paling tidak seseorang memiliki perilaku yang dapat dipahami.

Ayo lihat...

HttpUtility.UrlEncode(" ") == "+" //breaks ASP.NET when used in paths, non-
                                  //standard, undocumented.
Uri.EscapeUriString("a?b=e") == "a?b=e" // makes sense, but rarely what you
                                        // want, since you still need to
                                        // escape special characters yourself

Tetapi favorit pribadi saya harus menjadi HttpUtility.UrlPathEncode - hal ini benar-benar tidak dapat dipahami. Ini mengkodekan:

  • "" ==> "% 20"
  • "100% true" ==> "100 %% 20true" (ok, url Anda rusak sekarang)
  • "test A.aspx # anchor B" ==> "test% 20A.aspx # anchor% 20B "
  • "test A.aspx? hmm # anchor B" ==> "test% 20A.aspx? hmm #anchor B " ( perhatikan perbedaannya dengan urutan escape sebelumnya! )

Ia juga memiliki dokumentasi MSDN yang sangat spesifik "Mengkodekan bagian jalur dari string URL untuk transmisi HTTP yang andal dari server Web ke klien." - tanpa benar-benar menjelaskan apa fungsinya. Anda cenderung menembak diri sendiri di kaki dengan ...

Singkatnya, tetap menggunakan Uri.EscapeDataString .

Eamon Nerbonne
sumber
4
Dan sayangnya itu masih tidak berfungsi ketika melakukan permintaan HTTP terhadap beberapa server web - Uri.EscapeDataString () tidak menyandikan "!" atau "'", yang berbeda dari cara sebagian besar implementasi browser escape () berfungsi ...
Chris R. Donnelly
6
! dan 'karakter tidak seharusnya disandikan; tetapi jika server web buggy membutuhkan ini, mudah untuk menyelesaikannya. Hindari fungsi pelarian javascript - itu sifatnya buggy (mustahil untuk bolak-balik, untuk satu). Lihat xkr.us/articles/javascript/encode-compare - tetapi singkatnya; Anda dapat menggunakan encodeUriComponent () sebagai gantinya, yang berperilaku mirip dengan EscapeDataString - itu dapat diprediksi dan dibalik menyandikan string, dan juga tidak menyandikan! dan 'karakter.
Eamon Nerbonne
2
Ini sudah lama, tetapi pertanyaannya terbentur ke halaman depan, jadi .... Bagian jalur dari string url adalah bagian antara domain dan? atau # dalam url.
Powerlord
2
@Tim: mungkin ada beberapa ?dan siapa yang mengatakan yang harus dikodekan dan yang berfungsi sebagai pemisah? Adapun ruang: dalam kedua kasus ruang di hash, sehingga ada atau tidak adanya fragmen kueri seharusnya tidak masalah. Dan akhirnya, tidak dapat dimaafkan untuk merusak Uri seperti pada contoh kedua yang berisi%. The UrlPathEncodeMetode ini polos borked dan tidak boleh digunakan.
Eamon Nerbonne
1
Saya pikir jawaban saya di stackoverflow.com/a/13993486/237091 dapat sedikit menjelaskan penggunaan yang dimaksud dari UrlEncode / UrlPathEncode.
Scott Stafford
60

Maju cepat hampir 9 tahun sejak ini pertama kali ditanyakan, dan di dunia .NET Core dan .NET Standard, sepertinya opsi yang paling umum yang kita miliki untuk pengkodean URL adalah WebUtility.UrlEncode (di bawah System.Net) dan Uri.EscapeDataString . Dilihat oleh jawaban paling populer di sini dan di tempat lain, Uri.EscapeDataString tampaknya lebih disukai. Tetapi apakah itu? Saya melakukan beberapa analisis untuk memahami perbedaan dan inilah yang saya temukan:

Untuk keperluan pengkodean URL, karakter sesuai dengan salah satu dari 3 kategori: tidak dapat diterima (legal dalam URL); dilindungi undang-undang (legal tetapi memiliki makna khusus, jadi Anda mungkin ingin menyandikannya); dan yang lainnya (harus selalu dikodekan).

Menurut RFC , karakter yang dipesan adalah::/?#[]@!$&'()*+,;=

Dan karakter tanpa syarat adalah alfanumerik dan -._~

Putusan

Uri.EscapeDataString dengan jelas mendefinisikan misinya:% -encode semua karakter yang dilindungi undang-undang dan ilegal. WebUtility.UrlEncode lebih ambigu dalam definisi dan implementasi. Anehnya, itu mengkodekan beberapa karakter yang dilindungi undang-undang tetapi tidak yang lain (mengapa tanda kurung dan bukan tanda kurung ??), dan orang asing masih mengkode ~karakter yang tidak bersalah .

Oleh karena itu, saya setuju dengan saran populer - gunakan Uri.EscapeDataString bila memungkinkan, dan pahami bahwa karakter yang dicadangkan suka /dan ?akan disandikan. Jika Anda perlu berurusan dengan string yang berpotensi besar, terutama dengan konten formulir yang disandikan URL, Anda harus kembali ke WebUtility.UrlEncode dan menerima kebiasaannya, atau mengatasi masalah tersebut.


EDIT: Saya sudah berusaha untuk memperbaiki SEMUA kebiasaan yang disebutkan di atas di Flurl melalui Url.Encode, Url.EncodeIllegalCharactersdan Url.Decodemetode statis. Ini ada dalam paket inti (yang kecil dan tidak termasuk semua barang HTTP), atau merasa bebas untuk mengambilnya dari sumbernya. Saya menyambut setiap komentar / umpan balik yang Anda miliki tentang ini.


Berikut kode yang saya gunakan untuk menemukan karakter mana yang dikodekan secara berbeda:

var diffs =
    from i in Enumerable.Range(0, char.MaxValue + 1)
    let c = (char)i
    where !char.IsHighSurrogate(c)
    let diff = new {
        Original = c,
        UrlEncode = WebUtility.UrlEncode(c.ToString()),
        EscapeDataString = Uri.EscapeDataString(c.ToString()),
    }
    where diff.UrlEncode != diff.EscapeDataString
    select diff;

foreach (var diff in diffs)
    Console.WriteLine($"{diff.Original}\t{diff.UrlEncode}\t{diff.EscapeDataString}");
Todd Menier
sumber
2
Ini brilian!
Jorge Aguirre
1
Pekerjaan bagus memverifikasi solusi yang disarankan pada kerangka .net modern.
Neowizard
Harus disebutkan bahwa ada beberapa perbedaan antara WebUtility dan HttpUtility . WebUtility menggunakan huruf besar dan HttpUtility menggunakan huruf kecil untuk entitas hexa. Selain itu, HttpUtility tidak termasuk dalam versi subset lama dari .NET Framework "Profil Klien". WebUtility tersedia dari .NET Framework 4.0.
tibx
28

Ingatlah bahwa Anda sebaiknya tidak menggunakan salah satu dari metode tersebut. Perpustakaan Scripting Situs Anti-Lintas Microsoft mencakup penggantian untuk HttpUtility.UrlEncodedan HttpUtility.HtmlEncodeyang keduanya lebih sesuai standar, dan lebih aman. Sebagai bonus, Anda mendapatkan JavaScriptEncodemetode juga.

Joel Mueller
sumber
Setelah membaca dokumentasi dan FAQ pada tautan yang disediakan, saya yakin jawaban ini adalah cara terbaik dan paling aman untuk menyandikan data! Terima kasih banyak untuk berbagi ini!
Sudhanshu Mishra
Tautan tidak berfungsi lagi. Apa metode penggantiannya?
Edward Brey
@EdwardBrey Ini adalah versi terbaru dari perpustakaan scripting situs Anti-Cross: microsoft.com/en-au/download/details.aspx?id=28589
Sudhanshu Mishra
11

Server.UrlEncode () ada untuk memberikan kompatibilitas dengan Classic ASP,

Server.UrlEncode(str);

Setara dengan:

HttpUtility.UrlEncode(str, Response.ContentEncoding);
CMS
sumber
5

Yang sama, Server.UrlEncode()panggilanHttpUtility.UrlEncode()

andleer
sumber