Sự khác biệt giữa EscapeUriString và EscapeDataString là gì?


192

Nếu chỉ đối phó với mã hóa url, tôi nên sử dụng EscapeUriString ?


10
Luôn thoát từng giá trị riêng lẻ bằng cách sử dụng 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ể.
Timo

Câu trả lời:


112

EscapeDataStringLuô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


3
Tôi không chắc chắn rằng liên kết thực sự cung cấp nhiều thông tin hơn vì nó liên quan đến việc không chú ý hơn là sau đó thực hiện.
Steven

1
Về cơ bản là giống nhau. Nếu bạn thực sự đọc bài báo, có một cái bàn ở giữa thực sự thoát ra (không phải là hình ảnh không rõ ràng) để hiển thị sự khác biệt (so sánh với URLEncodequá).
Jcl

2
Tôi vẫn chưa rõ ràng - điều gì xảy ra nếu tôi không thoát toàn bộ URI mà chỉ là một phần của nó - (tức là dữ liệu cho tham số chuỗi truy vấn)? Tôi đang thoát dữ liệu cho URI hay EscapeDataString có ngụ ý điều gì đó hoàn toàn khác không?
BrainSlugs83

4
... đã thực hiện một số thử nghiệm có vẻ như tôi muốn EscapeDataString cho tham số URI. Tôi đã thử nghiệm với chuỗi "I heart C ++" và EscapeUriString không mã hóa các ký tự "+", nó chỉ để lại như vậy, EscapeDataString đã chuyển đổi chính xác chúng thành "% 2B".
BrainSlugs83

7
Đây là một câu trả lời xấu. Bạn không bao giờ nên sử dụng EscapeUriString, nó không có nghĩa gì cả. Xem câu trả lời của Livven bên dưới (và nâng cao nó).
Brandon Paddock

241

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ể:

  1. Bạn có một URI đơn giản, như thế này:

    http://example.org/

    Uri.EscapeUriString sẽ không thay đổi nó.

  2. 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
  3. 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.EscapeUriStringvì 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.

  4. Bạn quyết định rằng trên thực tế bạn muốn keytham 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.EscapeUriStringcũ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.EscapeUriStringcho 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.EscapeUriStringcũ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.EscapeDataStringcho 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.EscapeUriStringnhư 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.


4
Wow, cảm ơn bạn cuối cùng đã làm rõ vấn đề này. Hai câu trả lời trước không hữu ích lắm.
EverPftime

3
Hoàn toàn chính xác. EscapeUriString (như hành vi mặc định của EscapeUrl trong Win32) được tạo bởi một người không hiểu URI hoặc thoát. Đó là một nỗ lực sai lầm để tạo ra thứ gì đó có URI không đúng định dạng và đôi khi biến nó thành phiên bản dự định. Nhưng nó không có thông tin cần thiết để làm điều này một cách đáng tin cậy. Nó cũng thường xuyên được sử dụng thay cho EscapeDataString, điều này cũng rất có vấn đề. Tôi ước EscapeUriString không tồn tại. Mỗi lần sử dụng đều sai.
Brandon Paddock

4
giải thích độc đáo +1 đó là cách tốt hơn so với câu trả lời chỉ được chấp nhận
Ehsan Sajjad

1
Câu trả lời này cần được chú ý nhiều hơn. Đây là cách chính xác để làm điều đó. Các câu trả lời khác có kịch bản mà chúng không tạo ra kết quả như mong muốn.
Timo

1
... Chắc chắn encodeURI/ Uri.EscapeUriStringkhô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ó.
Lưỡi liềm tươi

56

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":

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

Đó là một URI hợp lệ (thử nó) và EscapeUriStringsẽ không sửa đổi nó.

Bây giờ hãy xem xét truy vấn Google cho "happy c ++":

https://www.google.com/?q=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 EscapeDataStringvà voila * :

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

*) 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 UriBuildernhư bình thường, thì bạn chỉ cần EscapeDataStringthoá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.


Cảm ơn. Thế còn khi bạn có một chuỗi URI tuyệt đối mà bạn cần mã hóa, chẳng hạn "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?
wensveen

Nếu bạn chuyển toàn bộ URL dưới dạng tham số sang URL khác, thì hãy sử dụng EscapeDataString. Nếu URL bạn cung cấp là URL thực tế, thì có, bạn muốn tách ra ?.
Seth

7

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 . EscapeDataStringthoát khỏi chúng; EscapeUriStringkhô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ệmEscapeUriStringlà á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ĩ EscapeUriStringsẽ 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.


1

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
*/
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.