ความแตกต่างระหว่าง EscapeUriString และ EscapeDataString คืออะไร


195

หากจัดการกับการเข้ารหัส URL เท่านั้นฉันควรใช้EscapeUriString ?


10
มักจะหลบหนีแต่ละค่าใช้Uri.EscapeDataString()ตามที่อธิบายไว้ในคำตอบ @ Livven ของ ด้วยวิธีการอื่น ๆ ระบบจะไม่มีข้อมูลเพียงพอที่จะสร้างผลลัพธ์ที่ต้องการสำหรับอินพุตที่เป็นไปได้
Timo

คำตอบ:


112

ใช้EscapeDataStringเสมอ (สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสาเหตุดูคำตอบของ Livvenด้านล่าง)

แก้ไข : ลบลิงค์ที่ไม่ทำงานออกไปเพื่อให้การเข้ารหัสทั้งสองแตกต่าง


3
ฉันไม่แน่ใจว่าลิงก์นั้นให้ข้อมูลมากกว่านี้เพราะมันเกี่ยวกับการหลบหลีกแทนที่จะหลบหนี
สตีเวน

1
มันแตกต่างกันโดยทั่วไป หากคุณอ่านบทความจริง ๆ แล้วมีตารางอยู่ตรงกลางที่หลบหนี (ไม่ใช่ unescapes) เพื่อแสดงความแตกต่าง (เปรียบเทียบด้วยURLEncode)
Jcl

2
ยังไม่ชัดเจนสำหรับฉัน - จะเป็นอย่างไรถ้าฉันไม่ได้ยกเว้น URI ทั้งหมด แต่เป็นเพียงส่วนหนึ่งของมัน - (เช่นข้อมูลสำหรับพารามิเตอร์สตริงข้อความค้นหา) ฉันกำลังหลบหนีข้อมูลสำหรับ URI หรือไม่หรือ EscapeDataString บ่งบอกถึงบางสิ่งที่แตกต่างอย่างสิ้นเชิง?
BrainSlugs83

4
... การทดสอบบางอย่างดูเหมือนว่าฉันต้องการ EscapeDataString สำหรับพารามิเตอร์ URI ฉันทดสอบด้วยสตริง "I heart C ++" และ EscapeUriString ไม่ได้เข้ารหัสอักขระ "+" มันเหลือเพียงอย่างเดียวคือ EscapeDataString แปลงเป็น "% 2B" อย่างถูกต้อง
BrainSlugs83

7
นี่เป็นคำตอบที่ไม่ดี คุณไม่ควรใช้ EscapeUriString มันไม่สมเหตุสมผล ดูคำตอบของ Livven ด้านล่าง (และโหวตขึ้น)
Brandon Paddock

243

ฉันไม่พบคำตอบที่น่าพอใจดังนั้นฉันจึงตัดสินใจที่จะขุดลึกลงไปอีกเล็กน้อยเพื่อแก้ไขปัญหานี้ น่าแปลกที่คำตอบนั้นง่ายมาก:

มี (เกือบ *) Uri.EscapeUriStringไม่มีเหตุผลที่ถูกต้องเพื่อการใช้งานที่เคย Uri.EscapeDataStringหากคุณจำเป็นต้องร้อยละเข้ารหัสสตริงใช้เสมอ

* ดูย่อหน้าสุดท้ายสำหรับกรณีการใช้ที่ถูกต้อง

ทำไมนี้ ตามเอกสาร :

ใช้เมธอด EscapeUriString เพื่อเตรียมสตริง URI ที่ไม่ใช้ค่า Escape ให้เป็นพารามิเตอร์สำหรับตัวสร้าง Uri

มันไม่สมเหตุสมผลเลย ตามที่RFC 2396 :

URI อยู่ในรูปแบบ "หนี" เสมอเนื่องจากการหลบหนีหรือยกเลิกการหลีกเลี่ยง URI ที่เสร็จสมบูรณ์แล้วอาจเปลี่ยนความหมายของมัน

ในขณะที่ RFC ที่ยกมานั้นล้าสมัยโดยRFC 3986แต่ประเด็นก็ยังคงอยู่ ลองตรวจสอบโดยดูตัวอย่างที่เป็นรูปธรรม:

  1. คุณมี URI ง่ายๆเช่นนี้:

    http://example.org/

    Uri.EscapeUriString จะไม่เปลี่ยน

  2. คุณตัดสินใจที่จะแก้ไขสตริงแบบสอบถามด้วยตนเองโดยไม่คำนึงถึงการหลบหนี:

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

    Uri.EscapeUriString จะ (ถูกต้อง) หลบหนีพื้นที่สำหรับคุณ:

    http://example.org/?key=two%20words
  3. คุณตัดสินใจที่จะแก้ไขสตริงการสืบค้นด้วยตนเองยิ่งขึ้นไปอีก:

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

    อย่างไรก็ตามสตริงนี้จะไม่เปลี่ยนแปลงUri.EscapeUriStringเนื่องจากถือว่าแอมเปอร์แซนด์แสดงถึงการเริ่มต้นของคู่คีย์ - ค่าอื่น นี่อาจเป็นสิ่งที่คุณตั้งใจหรือไม่

  4. คุณตัดสินใจว่าจริง ๆ แล้วคุณต้องการให้keyพารามิเตอร์เป็นfather&sonดังนั้นคุณแก้ไข URL ก่อนหน้าด้วยตนเองโดยการหลีกเลี่ยงเครื่องหมายและ:

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

    อย่างไรก็ตามUri.EscapeUriStringจะหลีกเลี่ยงอักขระเปอร์เซ็นต์เช่นกันซึ่งนำไปสู่การเข้ารหัสสองครั้ง:

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

อย่างที่คุณเห็นการใช้Uri.EscapeUriStringเพื่อจุดประสงค์ทำให้ไม่สามารถใช้&เป็นส่วนหนึ่งของคีย์หรือค่าในสตริงเคียวรีแทนที่จะเป็นตัวคั่นระหว่างคู่คีย์ - ค่าหลายคู่

นี้เป็นเพราะในความพยายามที่จะทำให้มันเหมาะสำหรับการหลบหนี URI ที่เต็มรูปแบบก็ไม่สนใจตัวละครที่สงวนไว้และมีเพียงหนีตัวละครที่มีค่าลิขสิทธิ์หรือตรงไปตรงมาซึ่ง BTW เป็นตรงกันข้ามกับเอกสาร ในแบบที่คุณไม่ได้จบลงด้วยสิ่งที่ชอบhttp%3A%2F%2Fexample.org%2Fแต่คุณจะจบลงด้วยปัญหาที่แสดงด้านบน


ในท้ายที่สุดถ้า URI ของคุณถูกต้องแล้วก็ไม่จำเป็นต้องหลบหนีเพื่อส่งผ่านพารามิเตอร์ของ Uri construtor และถ้ามันไม่ถูกต้องการโทรUri.EscapeUriStringก็ไม่ใช่โซลูชันวิเศษ จริง ๆ แล้วมันจะทำงานในหลาย ๆ กรณีหากไม่ใช่กรณีส่วนใหญ่ แต่ก็ไม่น่าเชื่อถือ

คุณควรสร้าง URL และสตริงการสืบค้นของคุณเสมอโดยรวบรวมคู่คีย์ - ค่าและการเข้ารหัสเปอร์เซ็นต์แล้วเชื่อมต่อกับตัวคั่นที่จำเป็น คุณสามารถใช้Uri.EscapeDataStringเพื่อจุดประสงค์นี้ แต่ไม่สามารถใช้เพื่อUri.EscapeUriStringหลีกเลี่ยงอักขระที่สงวนไว้ตามที่กล่าวไว้ข้างต้น

เฉพาะในกรณีที่คุณไม่สามารถทำเช่นนั้นเมื่อจัดการกับ URIs ที่ผู้ใช้เป็นผู้ให้ใช้Uri.EscapeUriStringเป็นทางเลือกสุดท้าย แต่ข้อแม้ที่กล่าวถึงก่อนหน้านี้จะนำไปใช้ - หาก URI ที่ผู้ใช้ระบุไม่ชัดเจนผลลัพธ์อาจไม่เป็นที่ต้องการ


4
ว้าวขอขอบคุณสำหรับการชี้แจงปัญหานี้ในที่สุด คำตอบสองข้อก่อนหน้านี้ไม่เป็นประโยชน์มาก
EverPresent

3
ถูกต้อง EscapeUriString (เช่นพฤติกรรมเริ่มต้นของ EscapeUrl ใน Win32) ถูกสร้างขึ้นโดยคนที่ไม่เข้าใจ URIs หรือหลบหนี มันเป็นความพยายามที่เข้าใจผิดในการสร้างสิ่งที่ใช้ URI ที่มีรูปแบบไม่ถูกต้องและบางครั้งเปลี่ยนเป็นรุ่นที่ตั้งใจ แต่มันไม่มีข้อมูลที่ต้องทำอย่างน่าเชื่อถือ นอกจากนี้ยังมักถูกใช้แทน EscapeDataString ซึ่งเป็นปัญหาเช่นกัน ฉันหวังว่าไม่มี EscapeUriString การใช้งานทุกครั้งมันผิด
Brandon Paddock

4
อย่างอธิบาย +1 มันเป็นวิธีที่ดีกว่าการเชื่อมโยงได้รับการยอมรับคำตอบเดียว
Ehsan Sajjad

1
คำตอบนี้ต้องการความสนใจมากขึ้น มันเป็นวิธีที่ถูกต้องที่จะทำ คำตอบอื่น ๆ มีสถานการณ์ที่พวกเขาไม่ได้ให้ผลลัพธ์ที่ต้องการ
Timo

1
... แน่นอนencodeURI/ Uri.EscapeUriStringไม่จำเป็นต้องบ่อยเท่าencodeURIComponent/ Uri.EscapeDataString(ตั้งแต่เมื่อไหร่ที่คุณใช้ URL ที่ต้องใช้ในบริบท uri) แต่นั่นไม่ได้หมายความว่ามันไม่มีที่อยู่
Crescent Fresh

56

อักขระเครื่องหมายบวก (+) สามารถเปิดเผยได้มากมายเกี่ยวกับความแตกต่างระหว่างวิธีการเหล่านี้ ใน URI แบบง่ายอักขระเครื่องหมายบวกหมายถึง "ช่องว่าง" พิจารณาสอบถาม Google เพื่อ "แมวมีความสุข":

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

นั่นคือ URI ที่ถูกต้อง (ลองใช้) และEscapeUriStringจะไม่แก้ไข

ตอนนี้ให้ลองค้นหาคำว่า "happy c ++" ของ Google:

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

นั่นคือ URI ที่ถูกต้อง (ลองใช้) แต่มันจะทำการค้นหา "happy c" เพราะทั้งสองมีการตีความว่าเป็นช่องว่าง หากต้องการแก้ไขเราสามารถส่ง "happy c ++" ไปที่EscapeDataStringและ voila * :

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

*)สตริงข้อมูลที่เข้ารหัสเป็นจริง "ความสุข% 20c% 2B% 2B"; % 20 เป็นฐานสิบหกสำหรับอักขระเว้นวรรคและ% 2B เป็นเลขฐานสิบหกสำหรับอักขระเครื่องหมายบวก

หากคุณใช้UriBuilderตามที่ควรจะเป็นคุณจะต้องEscapeDataStringหลีกเลี่ยงองค์ประกอบบางส่วนของ URI ทั้งหมดของคุณอย่างถูกต้อง @ คำตอบ Livven EscapeUriStringของคำถามต่อไปนี้พิสูจน์ให้เห็นว่ามีจริงๆเหตุผลที่จะใช้ไม่ได้


ขอบคุณ สิ่งที่เกี่ยวกับเมื่อคุณมีสตริง URI "https://www.google.com/?q=happy c++"แน่นอนว่าคุณจะต้องเข้ารหัสเช่น ดูเหมือนว่าฉันต้องแยกด้วยตนเอง "?" หรือมีวิธีที่ดีกว่า?
wensveen

หากคุณส่ง URL ทั้งหมดเป็นพารามิเตอร์ไปยัง URL EscapeDataStringอื่นแล้วใช้ หาก URL ที่คุณระบุเป็น URL จริงคุณต้องแยกจาก?กัน
เซ

7

ความคิดเห็นในแหล่งที่อยู่ที่แตกต่างอย่างชัดเจน เหตุใดข้อมูลนี้จึงไม่ถูกส่งต่อผ่านความคิดเห็นเอกสาร XML เป็นเรื่องลึกลับสำหรับฉัน

EscapeUriString:

วิธีนี้จะหลีกเลี่ยงอักขระใด ๆ ที่ไม่ใช่อักขระที่สงวนไว้หรือที่ไม่ได้จองรวมถึงเครื่องหมายเปอร์เซ็นต์ โปรดทราบว่า EscapeUriString จะไม่หนีเครื่องหมาย '#'

EscapeDataString:

วิธีนี้จะหลีกเลี่ยงตัวละครที่ไม่ใช่ตัวละครที่ไม่ได้จองรวมถึงเครื่องหมายเปอร์เซ็นต์

ดังนั้นความแตกต่างคือวิธีจัดการอักขระที่สงวนไว้ EscapeDataStringหลบหนีพวกเขา; EscapeUriStringไม่.

ตามRFCตัวละครที่สงวนไว้คือ::/?#[]@!$&'()*+,;=

เพื่อความสมบูรณ์อักขระที่ไม่ได้จองจะเป็นตัวอักษรและตัวเลข -._~

ทั้งสองวิธียกเว้นอักขระที่ไม่ได้จองหรือไม่ได้รับการสำรอง

ฉันไม่เห็นด้วยกับความคิดทั่วไปที่EscapeUriStringเป็นความชั่วร้าย ฉันคิดว่าวิธีที่หนีอักขระที่ผิดกฎหมายเท่านั้น(เช่นช่องว่าง) และอักขระที่สงวนไว้ไม่เป็นประโยชน์ แต่มันก็มีมุมมองที่แปลกประหลาดในการจัดการ%ตัวละคร อักขระที่เข้ารหัสเปอร์เซ็นต์ ( %ตามด้วยตัวเลขฐานสิบหก 2 ตัว) ถูกกฎหมายใน URI ฉันคิดว่าEscapeUriStringมันจะมีประโยชน์มากกว่านี้หากตรวจพบรูปแบบนี้และหลีกเลี่ยงการเข้ารหัส%เมื่อดำเนินการโดยเลขฐานสิบหก 2 หลักทันที


1

ตัวอย่างง่ายๆ

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
*/
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.