คำตอบ:
ใช้EscapeDataString
เสมอ (สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสาเหตุดูคำตอบของ Livvenด้านล่าง)
แก้ไข : ลบลิงค์ที่ไม่ทำงานออกไปเพื่อให้การเข้ารหัสทั้งสองแตกต่าง
URLEncode
)
ฉันไม่พบคำตอบที่น่าพอใจดังนั้นฉันจึงตัดสินใจที่จะขุดลึกลงไปอีกเล็กน้อยเพื่อแก้ไขปัญหานี้ น่าแปลกที่คำตอบนั้นง่ายมาก:
มี (เกือบ *) Uri.EscapeUriString
ไม่มีเหตุผลที่ถูกต้องเพื่อการใช้งานที่เคย Uri.EscapeDataString
หากคุณจำเป็นต้องร้อยละเข้ารหัสสตริงใช้เสมอ
* ดูย่อหน้าสุดท้ายสำหรับกรณีการใช้ที่ถูกต้อง
ทำไมนี้ ตามเอกสาร :
ใช้เมธอด EscapeUriString เพื่อเตรียมสตริง URI ที่ไม่ใช้ค่า Escape ให้เป็นพารามิเตอร์สำหรับตัวสร้าง Uri
มันไม่สมเหตุสมผลเลย ตามที่RFC 2396 :
URI อยู่ในรูปแบบ "หนี" เสมอเนื่องจากการหลบหนีหรือยกเลิกการหลีกเลี่ยง URI ที่เสร็จสมบูรณ์แล้วอาจเปลี่ยนความหมายของมัน
ในขณะที่ RFC ที่ยกมานั้นล้าสมัยโดยRFC 3986แต่ประเด็นก็ยังคงอยู่ ลองตรวจสอบโดยดูตัวอย่างที่เป็นรูปธรรม:
คุณมี URI ง่ายๆเช่นนี้:
http://example.org/
Uri.EscapeUriString
จะไม่เปลี่ยน
คุณตัดสินใจที่จะแก้ไขสตริงแบบสอบถามด้วยตนเองโดยไม่คำนึงถึงการหลบหนี:
http://example.org/?key=two words
Uri.EscapeUriString
จะ (ถูกต้อง) หลบหนีพื้นที่สำหรับคุณ:
http://example.org/?key=two%20words
คุณตัดสินใจที่จะแก้ไขสตริงการสืบค้นด้วยตนเองยิ่งขึ้นไปอีก:
http://example.org/?parameter=father&son
อย่างไรก็ตามสตริงนี้จะไม่เปลี่ยนแปลงUri.EscapeUriString
เนื่องจากถือว่าแอมเปอร์แซนด์แสดงถึงการเริ่มต้นของคู่คีย์ - ค่าอื่น นี่อาจเป็นสิ่งที่คุณตั้งใจหรือไม่
คุณตัดสินใจว่าจริง ๆ แล้วคุณต้องการให้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 ที่ผู้ใช้ระบุไม่ชัดเจนผลลัพธ์อาจไม่เป็นที่ต้องการ
encodeURI
/ Uri.EscapeUriString
ไม่จำเป็นต้องบ่อยเท่าencodeURIComponent
/ Uri.EscapeDataString
(ตั้งแต่เมื่อไหร่ที่คุณใช้ URL ที่ต้องใช้ในบริบท uri) แต่นั่นไม่ได้หมายความว่ามันไม่มีที่อยู่
อักขระเครื่องหมายบวก (+) สามารถเปิดเผยได้มากมายเกี่ยวกับความแตกต่างระหว่างวิธีการเหล่านี้ ใน URI แบบง่ายอักขระเครื่องหมายบวกหมายถึง "ช่องว่าง" พิจารณาสอบถาม Google เพื่อ "แมวมีความสุข":
นั่นคือ URI ที่ถูกต้อง (ลองใช้) และEscapeUriString
จะไม่แก้ไข
ตอนนี้ให้ลองค้นหาคำว่า "happy c ++" ของ Google:
นั่นคือ URI ที่ถูกต้อง (ลองใช้) แต่มันจะทำการค้นหา "happy c" เพราะทั้งสองมีการตีความว่าเป็นช่องว่าง หากต้องการแก้ไขเราสามารถส่ง "happy c ++" ไปที่EscapeDataString
และ voila * :
*)สตริงข้อมูลที่เข้ารหัสเป็นจริง "ความสุข% 20c% 2B% 2B"; % 20 เป็นฐานสิบหกสำหรับอักขระเว้นวรรคและ% 2B เป็นเลขฐานสิบหกสำหรับอักขระเครื่องหมายบวก
หากคุณใช้UriBuilder
ตามที่ควรจะเป็นคุณจะต้องEscapeDataString
หลีกเลี่ยงองค์ประกอบบางส่วนของ URI ทั้งหมดของคุณอย่างถูกต้อง @ คำตอบ Livven EscapeUriString
ของคำถามต่อไปนี้พิสูจน์ให้เห็นว่ามีจริงๆเหตุผลที่จะใช้ไม่ได้
"https://www.google.com/?q=happy c++"
แน่นอนว่าคุณจะต้องเข้ารหัสเช่น ดูเหมือนว่าฉันต้องแยกด้วยตนเอง "?" หรือมีวิธีที่ดีกว่า?
EscapeDataString
อื่นแล้วใช้ หาก URL ที่คุณระบุเป็น URL จริงคุณต้องแยกจาก?
กัน
ความคิดเห็นในแหล่งที่อยู่ที่แตกต่างอย่างชัดเจน เหตุใดข้อมูลนี้จึงไม่ถูกส่งต่อผ่านความคิดเห็นเอกสาร XML เป็นเรื่องลึกลับสำหรับฉัน
EscapeUriString:
วิธีนี้จะหลีกเลี่ยงอักขระใด ๆ ที่ไม่ใช่อักขระที่สงวนไว้หรือที่ไม่ได้จองรวมถึงเครื่องหมายเปอร์เซ็นต์ โปรดทราบว่า EscapeUriString จะไม่หนีเครื่องหมาย '#'
EscapeDataString:
วิธีนี้จะหลีกเลี่ยงตัวละครที่ไม่ใช่ตัวละครที่ไม่ได้จองรวมถึงเครื่องหมายเปอร์เซ็นต์
ดังนั้นความแตกต่างคือวิธีจัดการอักขระที่สงวนไว้ EscapeDataString
หลบหนีพวกเขา; EscapeUriString
ไม่.
ตามRFCตัวละครที่สงวนไว้คือ::/?#[]@!$&'()*+,;=
เพื่อความสมบูรณ์อักขระที่ไม่ได้จองจะเป็นตัวอักษรและตัวเลข -._~
ทั้งสองวิธียกเว้นอักขระที่ไม่ได้จองหรือไม่ได้รับการสำรอง
ฉันไม่เห็นด้วยกับความคิดทั่วไปที่EscapeUriString
เป็นความชั่วร้าย ฉันคิดว่าวิธีที่หนีอักขระที่ผิดกฎหมายเท่านั้น(เช่นช่องว่าง) และอักขระที่สงวนไว้ไม่เป็นประโยชน์ แต่มันก็มีมุมมองที่แปลกประหลาดในการจัดการ%
ตัวละคร อักขระที่เข้ารหัสเปอร์เซ็นต์ ( %
ตามด้วยตัวเลขฐานสิบหก 2 ตัว) ถูกกฎหมายใน URI ฉันคิดว่าEscapeUriString
มันจะมีประโยชน์มากกว่านี้หากตรวจพบรูปแบบนี้และหลีกเลี่ยงการเข้ารหัส%
เมื่อดำเนินการโดยเลขฐานสิบหก 2 หลักทันที
ตัวอย่างง่ายๆ
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
*/
Uri.EscapeDataString()
ตามที่อธิบายไว้ในคำตอบ @ Livven ของ ด้วยวิธีการอื่น ๆ ระบบจะไม่มีข้อมูลเพียงพอที่จะสร้างผลลัพธ์ที่ต้องการสำหรับอินพุตที่เป็นไปได้