Apa perbedaan antara EscapeUriString dan EscapeDataString?

192

Jika hanya berurusan dengan penyandian url, saya harus menggunakan EscapeUriString ?

pengguna496949
sumber
10
Selalu lepaskan setiap nilai individu menggunakan Uri.EscapeDataString(), seperti yang dijelaskan dalam jawaban @ Livven. Dengan pendekatan lain, sistem tidak memiliki cukup informasi untuk menghasilkan hasil yang diinginkan untuk setiap input yang mungkin.
Timo

Jawaban:

112

Gunakan EscapeDataStringselalu (untuk info lebih lanjut tentang alasannya, lihat jawaban Livven di bawah)

Sunting : menghapus tautan mati ke bagaimana keduanya berbeda dalam pengodean

Jcl
sumber
3
Saya tidak yakin tautan itu benar-benar memberikan lebih banyak informasi karena ini berkaitan dengan penghapusan daripada melarikan diri.
Steven
1
Pada dasarnya perbedaannya sama. Jika Anda benar-benar membaca artikel, ada tabel di tengah yang benar-benar lolos (bukan unescapes) untuk menunjukkan perbedaannya (dibandingkan dengan URLEncodeterlalu).
Jcl
2
Ini masih tidak jelas bagi saya - bagaimana jika saya tidak melarikan diri dari URI keseluruhan tetapi hanya sebagian darinya - (yaitu data untuk parameter string kueri)? Apakah saya melarikan diri data untuk URI, atau apakah EscapeDataString menyiratkan sesuatu yang sama sekali berbeda?
BrainSlugs83
4
... melakukan beberapa pengujian sepertinya saya ingin EscapeDataString untuk parameter URI. Saya menguji dengan string "I heart C ++" dan EscapeUriString tidak menyandikan karakter "+", itu hanya membiarkan mereka apa adanya, EscapeDataString dengan benar mengubahnya menjadi "% 2B".
BrainSlugs83
7
Ini jawaban yang buruk. Anda seharusnya tidak pernah menggunakan EscapeUriString, itu tidak masuk akal. Lihat jawaban Livven di bawah ini (dan angkat suara).
Brandon Paddock
242

Saya tidak menemukan jawaban yang ada memuaskan, jadi saya memutuskan untuk menggali sedikit lebih dalam untuk menyelesaikan masalah ini. Anehnya, jawabannya sangat sederhana:

Ada (hampir *) tidak ada alasan valid untuk menggunakannya Uri.EscapeUriString. Jika Anda perlu meng-enkode string, selalu gunakan Uri.EscapeDataString.

* Lihat paragraf terakhir untuk kasus penggunaan yang valid.

Kenapa ini? Menurut dokumentasi :

Gunakan metode EscapeUriString untuk menyiapkan string URI yang tidak terhapus untuk menjadi parameter bagi konstruktor Uri.

Ini tidak masuk akal. Menurut RFC 2396 :

URI selalu dalam bentuk "melarikan diri", karena melarikan diri atau melepaskan URI yang lengkap dapat mengubah semantiknya.

Sementara RFC yang dikutip telah usang oleh RFC 3986 , intinya masih berdiri. Mari kita verifikasi dengan melihat beberapa contoh nyata:

  1. Anda memiliki URI sederhana, seperti ini:

    http://example.org/

    Uri.EscapeUriString tidak akan mengubahnya.

  2. Anda memutuskan untuk mengedit string kueri secara manual tanpa mempertimbangkan untuk melarikan diri:

    http://example.org/?key=two words

    Uri.EscapeUriString akan (dengan benar) keluar dari ruang untuk Anda:

    http://example.org/?key=two%20words
  3. Anda memutuskan untuk mengedit string kueri secara manual lebih jauh:

    http://example.org/?parameter=father&son

    Namun, string ini tidak diubah oleh Uri.EscapeUriString, karena mengasumsikan ampersand menandakan dimulainya pasangan nilai kunci lainnya. Ini mungkin atau mungkin bukan apa yang Anda maksudkan.

  4. Anda memutuskan bahwa Anda sebenarnya menginginkan keyparameternya father&son, jadi Anda memperbaiki URL sebelumnya secara manual dengan keluar dari ampersand:

    http://example.org/?parameter=father%26son

    Namun, Uri.EscapeUriStringakan keluar dari karakter persen juga, yang mengarah ke pengkodean ganda:

    http://example.org/?parameter=father%2526son

Seperti yang Anda lihat, menggunakan Uri.EscapeUriStringuntuk tujuan yang dimaksudkan membuatnya tidak mungkin untuk digunakan &sebagai bagian dari kunci atau nilai dalam string kueri alih-alih sebagai pemisah antara beberapa pasangan nilai kunci.

Ini karena, dalam upaya membuatnya cocok untuk keluar dari URI penuh, ia mengabaikan karakter yang dipesan dan hanya lolos karakter yang tidak dilindungi atau tidak dilindungi, yang, BTW, bertentangan dengan dokumentasi . Dengan cara ini Anda tidak berakhir dengan sesuatu seperti http%3A%2F%2Fexample.org%2F, tetapi Anda berakhir dengan masalah yang digambarkan di atas.


Pada akhirnya, jika URI Anda valid, itu tidak perlu diloloskan untuk dilewatkan sebagai parameter ke konstruktor Uri, dan jika itu tidak valid maka menelepon Uri.EscapeUriStringjuga bukan solusi ajaib. Sebenarnya, ini akan berfungsi dalam banyak kasus, jika tidak dalam banyak kasus, tetapi tidak dapat diandalkan.

Anda harus selalu membuat URL dan string kueri dengan mengumpulkan pasangan nilai kunci dan pengkodean persen lalu menggabungkannya dengan pemisah yang diperlukan. Anda dapat menggunakan Uri.EscapeDataStringuntuk tujuan ini, tetapi tidakUri.EscapeUriString , karena itu tidak luput dari karakter yang dipesan, seperti yang disebutkan di atas.

Hanya jika Anda tidak dapat melakukan itu, misalnya ketika berhadapan dengan URI yang disediakan pengguna, apakah masuk akal untuk digunakan Uri.EscapeUriStringsebagai upaya terakhir. Tetapi peringatan yang disebutkan sebelumnya berlaku - jika URI yang diberikan pengguna ambigu, hasilnya mungkin tidak diinginkan.

Livven
sumber
4
Wow, terima kasih untuk akhirnya mengklarifikasi masalah ini. Dua jawaban sebelumnya tidak terlalu membantu.
EverPresent
3
Benar sekali. EscapeUriString (seperti perilaku default EscapeUrl di Win32) dibuat oleh seseorang yang tidak memahami URI atau melarikan diri. Ini adalah upaya yang salah arah untuk membuat sesuatu yang mengambil URI cacat dan terkadang mengubahnya menjadi versi yang dimaksud. Tetapi tidak memiliki informasi yang dibutuhkan untuk melakukan ini dengan andal. Itu juga sering digunakan di tempat EscapeDataString yang juga sangat bermasalah. Saya berharap EscapeUriString tidak ada. Setiap penggunaannya salah.
Brandon Paddock
4
menjelaskan +1 dengan baik, itu jauh lebih baik daripada jawaban tautan saja yang diterima
Ehsan Sajjad
1
Jawaban ini perlu lebih diperhatikan. Ini adalah cara yang benar untuk melakukannya. Jawaban lain memiliki skenario di mana mereka tidak menghasilkan hasil yang diinginkan.
Timo
1
... Tentu encodeURI/ Uri.EscapeUriStringtidak diperlukan sesering encodeURIComponent/ Uri.EscapeDataString(karena kapan Anda deaing dengan url buta yang harus digunakan dalam konteks uri), tetapi itu tidak berarti itu tidak memiliki tempatnya.
Crescent Fresh
56

Karakter plus (+) dapat mengungkapkan banyak tentang perbedaan antara metode ini. Dalam URI sederhana, karakter plus berarti "ruang". Pertimbangkan meminta Google untuk "kucing bahagia":

https://www.google.com/?q=happy+cat

Itu URI yang valid (coba), dan EscapeUriStringtidak akan memodifikasinya.

Sekarang pertimbangkan untuk meminta Google untuk "happy c ++":

https://www.google.com/?q=happy+c++

Itu URI yang valid (coba saja), tetapi menghasilkan pencarian untuk "happy c", karena dua plus ditafsirkan sebagai spasi. Untuk memperbaikinya, kita dapat meneruskan "happy c ++" ke EscapeDataStringdan voila * :

https://www.google.com/?q=happy+c%2B%2B

*) String data yang disandikan sebenarnya "happy% 20c% 2B% 2B"; % 20 adalah hex untuk karakter spasi, dan% 2B adalah hex untuk karakter plus.

Jika Anda menggunakan UriBuildersebagaimana mestinya, maka Anda hanya perlu EscapeDataStringmelarikan diri dengan benar beberapa komponen seluruh URI Anda. @ Livven menjawab pertanyaan ini lebih lanjut membuktikan bahwa tidak ada alasan untuk menggunakannya EscapeUriString.

Seth
sumber
Terima kasih. Bagaimana ketika Anda memiliki string URI absolut yang harus Anda encode, misalnya "https://www.google.com/?q=happy c++". Sepertinya saya perlu membelah secara manual pada "?", Atau apakah ada cara yang lebih baik?
wensveen
Jika Anda meneruskan seluruh URL sebagai parameter ke URL lain, maka gunakan EscapeDataString. Jika URL yang Anda berikan adalah URL yang sebenarnya, maka ya Anda ingin membagi saja ?.
Seth
7

Komentar di sumber mengatasi perbedaan dengan jelas. Mengapa info ini tidak diajukan melalui dokumentasi dokumentasi komentar adalah misteri bagi saya.

EscapeUriString:

Metode ini akan lolos dari karakter apa pun yang bukan karakter yang dilindungi atau tidak dilindungi, termasuk tanda persen. Perhatikan bahwa EscapeUriString juga tidak akan keluar dari tanda '#'.

EscapeDataString:

Metode ini akan lolos dari karakter apa pun yang bukan karakter tanpa syarat, termasuk tanda persen.

Jadi perbedaannya adalah bagaimana mereka menangani karakter yang dipesan . EscapeDataStringlolos dari mereka;EscapeUriStringtidak.

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

Untuk kelengkapan, karakter tanpa syarat adalah alfanumerik dan -._~

Kedua metode lolos karakter yang tidak dilindungi undang-undang atau tidak dilindungi.

Saya tidak setuju dengan anggapan umum bahwa EscapeUriStringitu jahat. Saya pikir metode yang lolos hanya karakter ilegal (seperti spasi) dan karakter tidak dilindungi undang - undang berguna. Tetapi memang memiliki kekhasan dalam bagaimana menangani %karakter. Karakter yang dikodekan persen ( %diikuti oleh 2 digit hex) adalah legal dalam URI. Saya pikir EscapeUriStringakan jauh lebih berguna jika mendeteksi pola ini dan menghindari pengkodean %ketika segera diproses oleh 2 digit hex.

Todd Menier
sumber
1

Contoh sederhana

var data = "example.com/abc?DEF=あいう\x20えお";

Console.WriteLine(Uri.EscapeUriString(data));
Console.WriteLine(Uri.EscapeDataString(data));
Console.WriteLine(System.Net.WebUtility.UrlEncode(data));
Console.WriteLine(System.Web.HttpUtility.UrlEncode(data));

/*
=>
example.com/abc?DEF=%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A
example.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86%20%E3%81%88%E3%81%8A
example.com%2Fabc%3FDEF%3D%E3%81%82%E3%81%84%E3%81%86+%E3%81%88%E3%81%8A
example.com%2fabc%3fDEF%3d%e3%81%82%e3%81%84%e3%81%86+%e3%81%88%e3%81%8a
*/
Belajar
sumber