Câu trả lời:
EscapeDataString
Luôn luôn sử dụng (để biết thêm thông tin về lý do tại sao, hãy xem câu trả lời của Livven bên dưới)
Chỉnh sửa : loại bỏ liên kết chết để làm thế nào hai khác nhau về mã hóa
URLEncode
quá).
Tôi không tìm thấy câu trả lời thỏa đáng nên tôi quyết định đào sâu hơn một chút để giải quyết vấn đề này. Đáng ngạc nhiên, câu trả lời rất đơn giản:
Không có (hầu như *) không có lý do hợp lệ để sử dụng Uri.EscapeUriString
. Nếu bạn cần mã hóa phần trăm một chuỗi, luôn luôn sử dụng Uri.EscapeDataString
.
* Xem đoạn cuối cho trường hợp sử dụng hợp lệ.
Tại sao lại thế này? Theo tài liệu :
Sử dụng phương thức EscapeUriString để chuẩn bị một chuỗi URI không được giải mã thành một tham số cho hàm tạo Uri.
Điều này không thực sự có ý nghĩa. Theo RFC 2396 :
Một URI luôn ở dạng "thoát", vì thoát hoặc không tạo ra một URI đã hoàn thành có thể thay đổi ngữ nghĩa của nó.
Trong khi RFC được trích dẫn đã bị RFC 3986 lỗi thời , điểm vẫn còn. Hãy xác minh nó bằng cách xem xét một số ví dụ cụ thể:
Bạn có một URI đơn giản, như thế này:
http://example.org/
Uri.EscapeUriString
sẽ không thay đổi nó.
Bạn quyết định chỉnh sửa thủ công chuỗi truy vấn mà không cần quan tâm đến việc thoát:
http://example.org/?key=two words
Uri.EscapeUriString
sẽ (chính xác) thoát khỏi không gian cho bạn:
http://example.org/?key=two%20words
Bạn quyết định chỉnh sửa thủ công chuỗi truy vấn hơn nữa:
http://example.org/?parameter=father&son
Tuy nhiên, chuỗi này không bị thay đổi bởi Uri.EscapeUriString
vì nó giả sử ký hiệu và dấu hiệu bắt đầu của một cặp khóa-giá trị khác. Điều này có thể hoặc không thể là những gì bạn dự định.
Bạn quyết định rằng trên thực tế bạn muốn key
tham số trở thành father&son
, vì vậy bạn sửa URL trước bằng tay bằng cách thoát ký hiệu:
http://example.org/?parameter=father%26son
Tuy nhiên, Uri.EscapeUriString
cũng sẽ thoát ký tự phần trăm, dẫn đến mã hóa kép:
http://example.org/?parameter=father%2526son
Như bạn có thể thấy, sử dụng Uri.EscapeUriString
cho mục đích dự định của nó làm cho không thể sử dụng &
như một phần của khóa hoặc giá trị trong chuỗi truy vấn thay vì làm dấu tách giữa nhiều cặp giá trị khóa.
Điều này là do, trong nỗ lực làm cho nó phù hợp để thoát URI đầy đủ, nó bỏ qua các ký tự dành riêng và chỉ thoát các ký tự không dành riêng cũng như không được bảo vệ, điều này, BTW, trái với tài liệu . Bằng cách này, bạn không kết thúc với một cái gì đó như http%3A%2F%2Fexample.org%2F
, nhưng bạn kết thúc với các vấn đề được minh họa ở trên.
Cuối cùng, nếu URI của bạn hợp lệ, thì nó không cần phải thoát để được truyền dưới dạng tham số cho trình kết hợp Uri và nếu nó không hợp lệ thì việc gọi đó Uri.EscapeUriString
cũng không phải là một giải pháp ma thuật. Trên thực tế, nó sẽ hoạt động trong nhiều trường hợp nếu không phải hầu hết các trường hợp, nhưng nó không có nghĩa là đáng tin cậy.
Bạn phải luôn xây dựng các URL và chuỗi truy vấn của mình bằng cách thu thập các cặp giá trị khóa và mã hóa phần trăm và sau đó nối chúng với các dấu phân cách cần thiết. Bạn có thể sử dụng Uri.EscapeDataString
cho mục đích này, nhưng không Uri.EscapeUriString
, vì nó không thoát khỏi các ký tự dành riêng, như đã đề cập ở trên.
Chỉ khi bạn không thể làm điều đó, ví dụ như khi giao dịch với các URI do người dùng cung cấp, thì nó mới có ý nghĩa để sử dụng Uri.EscapeUriString
như là phương sách cuối cùng. Nhưng các cảnh báo được đề cập trước đây được áp dụng - nếu URI do người dùng cung cấp không rõ ràng, kết quả có thể không được mong muốn.
encodeURI
/ Uri.EscapeUriString
không cần thiết thường xuyên như encodeURIComponent
/ Uri.EscapeDataString
(kể từ khi bạn sử dụng các url mù phải được sử dụng trong ngữ cảnh uri), nhưng điều đó không có nghĩa là nó không có vị trí của nó.
Các ký tự dấu cộng (+) có thể tiết lộ rất nhiều về sự khác biệt giữa các phương thức này. Trong một URI đơn giản, ký tự dấu cộng có nghĩa là "khoảng trắng". Xem xét truy vấn Google cho "mèo hạnh phúc":
Đó là một URI hợp lệ (thử nó) và EscapeUriString
sẽ không sửa đổi nó.
Bây giờ hãy xem xét truy vấn Google cho "happy c ++":
Đó là một URI hợp lệ (thử nó), nhưng nó tạo ra một tìm kiếm cho "happy c", bởi vì hai dấu cộng được hiểu là khoảng trắng. Để khắc phục, chúng ta có thể chuyển "happy c ++" cho EscapeDataString
và voila * :
*) Chuỗi dữ liệu được mã hóa thực sự là "happy% 20c% 2B% 2B"; % 20 là hex cho ký tự khoảng trắng và% 2B là hex cho ký tự cộng.
Nếu bạn đang sử dụng UriBuilder
như bình thường, thì bạn chỉ cần EscapeDataString
thoát đúng một số thành phần của toàn bộ URI của mình. Câu trả lời của @ Livven cho câu hỏi này chứng tỏ rằng thực sự không có lý do để sử dụng EscapeUriString
.
"https://www.google.com/?q=happy c++"
. Có vẻ như tôi cần phải phân tách theo cách thủ công "?", Hoặc có cách nào tốt hơn không?
EscapeDataString
. Nếu URL bạn cung cấp là URL thực tế, thì có, bạn muốn tách ra ?
.
Nhận xét trong địa chỉ nguồn khác biệt rõ ràng. Tại sao thông tin này không được đưa ra thông qua các nhận xét tài liệu XML là một bí ẩn đối với tôi.
EscapeUriString:
Phương pháp này sẽ thoát khỏi bất kỳ ký tự nào không phải là ký tự dành riêng hoặc không được bảo vệ, bao gồm cả dấu phần trăm. Lưu ý rằng EscapeUriString cũng sẽ không thoát khỏi dấu '#'.
EscapeDataString:
Phương pháp này sẽ thoát khỏi bất kỳ ký tự nào không phải là ký tự không được kiểm soát, bao gồm cả dấu phần trăm.
Vì vậy, sự khác biệt là trong cách họ xử lý các nhân vật dành riêng . EscapeDataString
thoát khỏi chúng; EscapeUriString
không làm.
Theo RFC , các ký tự dành riêng là::/?#[]@!$&'()*+,;=
Để đầy đủ, các ký tự không được giám sát là chữ và số -._~
Cả hai phương thức đều thoát khỏi các ký tự không dành riêng cũng như không được bảo vệ.
Tôi không đồng ý với chung khái niệm mà EscapeUriString
là ác. Tôi nghĩ rằng một phương thức chỉ thoát các ký tự không hợp lệ (như khoảng trắng) và các ký tự không dành riêng là hữu ích. Nhưng nó có một sự châm biếm trong cách nó xử lý %
nhân vật. Các ký tự được mã hóa phần trăm ( %
theo sau là 2 chữ số hex) là hợp pháp trong một URI. Tôi nghĩ EscapeUriString
sẽ hữu ích hơn nhiều nếu nó phát hiện ra mẫu này và tránh mã hóa %
khi nó được tiến hành ngay lập tức bởi 2 chữ số hex.
Một ví dụ đơn giản
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()
, như được giải thích trong câu trả lời của @ Livven. Với các phương pháp khác, hệ thống đơn giản là không có đủ thông tin để tạo ra kết quả dự định cho mọi đầu vào có thể.