Làm thế nào để bạn UrlEncode mà không sử dụng System.Web?


310

Tôi đang cố gắng viết một ứng dụng máy khách windows gọi một trang web để lấy dữ liệu. Để giữ cho cài đặt ở mức tối thiểu, tôi đang cố gắng chỉ sử dụng các dll trong Hồ sơ khách hàng .NET Framework . Rắc rối là tôi cần UrlEncode một số tham số, có cách nào dễ dàng để thực hiện việc này mà không cần nhập System.Web.dll không phải là một phần của Client Pofile không?


Bạn có thể chỉ ra cách bạn thực hiện cuộc gọi đến trang web không? Có lẽ có một cái gì đó có thể được thực hiện ở đó.
Darin Dimitrov

Vì tò mò, làm thế nào để bạn gọi một trang web cho dữ liệu mà không sử dụng System.Web?
Patrick McDonald

@Patrick, có lẽ anh ta đang sử dụng WebRequesthoặc WebClient. Đó là lý do tôi hỏi về mã đặc biệt này bởi vì có những điều có thể được thực hiện về dữ liệu mã hóa url đúng.
Darin Dimitrov

1
Tôi đang sử dụng một đối tượng System.Net.WebRequest. Sau đó, tôi gọi GetRequestStream và viết các tham số Post của tôi ra luồng. Tôi cũng đặt ContentType thành "application / x-www-form-urlencoding".
Martin Brown

1
Tất nhiên, điều này cũng sẽ áp dụng tốt nếu tôi đang thực hiện yêu cầu NHẬN và nối các tham số vào URL.
Martin Brown

Câu trả lời:


317

System.Uri.EscapeUriString() có thể có vấn đề với một số ký tự nhất định, đối với tôi đó là ký hiệu số / pound '#' trong chuỗi.

Nếu đó là một vấn đề cho bạn, hãy thử:

System.Uri.EscapeDataString() //Works excellent with individual values

Đây là một câu trả lời câu hỏi SO giải thích sự khác biệt:

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

và khuyến nghị sử dụng Uri.EscapeDataString()trong bất kỳ khía cạnh nào.


1
Sai: blog.msdn.com/b/yangxind/archive/2006/11/09/ gợi ý Bạn sẽ gặp vấn đề với các dấu cộng vì chúng sẽ không được giải mã.
Chris Weber

7
Bài đăng trên blog đó hơi cũ và tôi chỉ cần "Uri thoát" một url đầy đủ và tất cả các khoảng trắng đã trở thành% 20, vì vậy tôi nghĩ họ đã sửa nó. Tôi đang sử dụng .Net 4.5.
Rodi

EscapeDataString cũng không hỗ trợ các chuỗi rất dài nếu bạn đang chuẩn bị dữ liệu cho thao tác POST. stackoverflow.com/questions/6695208/
trộm

Uri.EscapeUriStringthực sự rất có vấn đề và không nên được sử dụng, vì nó cố gắng làm một cái gì đó (thoát khỏi các URI đầy đủ) mà thực sự không thể làm một cách nhất quán Xem câu trả lời này để được giải thích chi tiết.
Livven

Cũng là một nhân vật không gian ''.
Waqas Shabbir

252

Trong .Net 4.5+ sử dụng WebUtility

Chỉ để định dạng tôi đang gửi đây là một câu trả lời.

Không thể tìm thấy bất kỳ ví dụ tốt so sánh chúng như vậy:

string testString = "http://test# space 123/text?var=val&another=two";
Console.WriteLine("UrlEncode:         " + System.Web.HttpUtility.UrlEncode(testString));
Console.WriteLine("EscapeUriString:   " + Uri.EscapeUriString(testString));
Console.WriteLine("EscapeDataString:  " + Uri.EscapeDataString(testString));
Console.WriteLine("EscapeDataReplace: " + Uri.EscapeDataString(testString).Replace("%20", "+"));

Console.WriteLine("HtmlEncode:        " + System.Web.HttpUtility.HtmlEncode(testString));
Console.WriteLine("UrlPathEncode:     " + System.Web.HttpUtility.UrlPathEncode(testString));

//.Net 4.0+
Console.WriteLine("WebUtility.HtmlEncode: " + WebUtility.HtmlEncode(testString));
//.Net 4.5+
Console.WriteLine("WebUtility.UrlEncode:  " + WebUtility.UrlEncode(testString));

Đầu ra:

UrlEncode:             http%3a%2f%2ftest%23+space+123%2ftext%3fvar%3dval%26another%3dtwo
EscapeUriString:       http://test#%20space%20123/text?var=val&another=two
EscapeDataString:      http%3A%2F%2Ftest%23%20space%20123%2Ftext%3Fvar%3Dval%26another%3Dtwo
EscapeDataReplace:     http%3A%2F%2Ftest%23+space+123%2Ftext%3Fvar%3Dval%26another%3Dtwo

HtmlEncode:            http://test# space 123/text?var=val&another=two
UrlPathEncode:         http://test#%20space%20123/text?var=val&another=two

//.Net 4.0+
WebUtility.HtmlEncode: http://test# space 123/text?var=val&another=two
//.Net 4.5+
WebUtility.UrlEncode:  http%3A%2F%2Ftest%23+space+123%2Ftext%3Fvar%3Dval%26another%3Dtwo

Trong .Net 4.5+ sử dụng WebUtility.UrlEncode

Điều này dường như sao chép HttpUtility.UrlEncode(trước v4.0) cho các ký tự phổ biến hơn:
Uri.EscapeDataString(testString).Replace("%20", "+").Replace("'", "%27").Replace("~", "%7E")
Lưu ý: EscapeUriStringsẽ giữ một chuỗi uri hợp lệ, khiến nó sử dụng càng nhiều ký tự văn bản càng tốt.

Xem câu trả lời này cho Bảng So sánh các bảng mã khác nhau:
https://stackoverflow.com/a/11236038/555798

Ngắt dòng Tất cả được liệt kê ở đây (trừ HttpUtility.HtmlEncode) sẽ chuyển đổi "\n\r"thành %0a%0dhoặc%0A%0D

Xin vui lòng chỉnh sửa này và thêm các ký tự mới vào chuỗi thử nghiệm của tôi hoặc để chúng trong các nhận xét và tôi sẽ chỉnh sửa nó.


Trong trường hợp của tôi, tôi đã phải sử dụng EscapeDataStringchứ không phải EscapeUriStringvì chúng tôi đã mã hóa lợi nhuận vận chuyển và nguồn cấp dữ liệu và những điều này đòi hỏi việc thoát hiểm tích cực hơn được thực hiện bởiEscapeDataString
David O'Meara

1
thêm ví dụ, bạn có thể cung cấp các trường hợp thử nghiệm của riêng bạn nếu bạn muốn. Đây là một ví dụ về việc chạy nó và các phương thức mã hóa khác cho thấy sự khác biệt dotnetfiddle.net/12IFw1
Maslow

3
WebUtility.UrlEncode () và WebUtility.UrlDecode () là 4,5+. Chúng không tồn tại trong 4.0.
Derek Kalweit

Msd nói: "Nền tảng Windows phổ quát: Có sẵn từ 4.5, .NET Framework: Có sẵn từ 4.0" ...
Thymine

54

Bạn có thể dùng

Uri.EscapeUriString (xem http://msdn.microsoft.com/en-us/l Library / system.uri.escapeuristring.aspx )


Có sự khác biệt giữa cái này và EscapeDataString không?
Martin Brown

3
Bạn muốn sử dụng EscapeUriString. EscapeUriString sẽ cố gắng mã hóa toàn bộ url (bao gồm http: // part) trong khi EscapeUriString hiểu phần nào thực sự cần được mã hóa
Matthew Manela

1
Tôi hiểu rồi, vì vậy trong trường hợp này có lẽ tôi sẽ muốn EscapeDataString vì tôi có thể muốn truyền URL dưới dạng tham số get. Tôi đang nối thêm một URL trong trường hợp này.
Martin Brown

5
@MatthewManela Tôi chắc chắn rằng bình luận Oct1 của bạn nên đọc EscapeDataString sẽ cố mã hóa ...
Maslow

Đừng sử dụng Uri.EscapeUriString. Nó không "hiểu" những phần nào nên được mã hóa, đó chỉ là một nỗ lực sai lầm khi làm một cái gì đó (thoát khỏi URI đầy đủ) mà thực sự không thể thực hiện một cách nhất quán. Xem câu trả lời này để được giải thích chi tiết.
Livven

20

Các câu trả lời ở đây rất tốt, nhưng vẫn không đủ cho tôi.

Tôi đã viết một vòng lặp nhỏ so sánh Uri.EscapeUriStringvới Uri.EscapeDataStringtất cả các ký tự từ 0 đến 255.

LƯU Ý: Cả hai chức năng đều có trí thông minh tích hợp mà các ký tự trên 0x80 được mã hóa UTF-8 đầu tiên và sau đó được mã hóa phần trăm.

Đây là kết quả:

******* Different *******

'#' -> Uri "#" Data "%23"
'$' -> Uri "$" Data "%24"
'&' -> Uri "&" Data "%26"
'+' -> Uri "+" Data "%2B"
',' -> Uri "," Data "%2C"
'/' -> Uri "/" Data "%2F"
':' -> Uri ":" Data "%3A"
';' -> Uri ";" Data "%3B"
'=' -> Uri "=" Data "%3D"
'?' -> Uri "?" Data "%3F"
'@' -> Uri "@" Data "%40"


******* Not escaped *******

'!' -> Uri "!" Data "!"
''' -> Uri "'" Data "'"
'(' -> Uri "(" Data "("
')' -> Uri ")" Data ")"
'*' -> Uri "*" Data "*"
'-' -> Uri "-" Data "-"
'.' -> Uri "." Data "."
'_' -> Uri "_" Data "_"
'~' -> Uri "~" Data "~"

'0' -> Uri "0" Data "0"
.....
'9' -> Uri "9" Data "9"

'A' -> Uri "A" Data "A"
......
'Z' -> Uri "Z" Data "Z"

'a' -> Uri "a" Data "a"
.....
'z' -> Uri "z" Data "z"

******* UTF 8 *******

.....
'Ò' -> Uri "%C3%92" Data "%C3%92"
'Ó' -> Uri "%C3%93" Data "%C3%93"
'Ô' -> Uri "%C3%94" Data "%C3%94"
'Õ' -> Uri "%C3%95" Data "%C3%95"
'Ö' -> Uri "%C3%96" Data "%C3%96"
.....

EscapeUriStringsẽ được sử dụng để mã hóa URL, trong khi EscapeDataStringđược sử dụng để mã hóa ví dụ nội dung của Cookie, vì dữ liệu Cookie không được chứa các ký tự dành riêng '='';'.


phân tích tốt đẹp và sự cố ở đây, rất hữu ích. nếu bất cứ ai có hoặc biết về điểm chuẩn hiệu suất (so sánh cả ba phương pháp) cũng sẽ rất tốt để xem
Shaun Wilson

Đây là một phân tích tốt và điều đáng nói là bạn không nên sử dụng Uri.EscapeUriString, vì việc thoát URI đầy đủ là không thể thực hiện một cách nhất quán. Xem câu trả lời này để được giải thích chi tiết.
Livven

16

Có một phiên bản hồ sơ khách hàng có thể sử dụng, lớp System.Net.WebUtility, có trong hồ sơ khách hàng System.dll. Đây là Liên kết MSDN:

Tính linh hoạt của web


Tôi lưu ý rằng trang trợ giúp cho lớp đó nói cụ thể "Cung cấp các phương thức mã hóa và giải mã URL khi xử lý các yêu cầu Web." vì vậy có thể là họ đã không đặt tên cho các phương thức tốt.
James White

Điểm hay, giả sử, tại sao bạn không bỏ phiếu cho anh em;) phiếu bầu này đã ám ảnh tôi suốt 2 năm! JK ... nhưng thành thật mà của lẽ lý do tại sao tôi đăng các liên kết, bất hạnh mà tôi phải mất một hit nổi tiếng về sai sót trong tài liệu của Microsoft ...
Sprague

11
Có vẻ như UrlEncode và UrlDecode chỉ được thêm vào WebUtility trong phiên bản 4.5 của .Net.
Martin Brown

8

Dưới đây là ví dụ về việc gửi yêu cầu POST mã hóa chính xác các tham số bằng cách sử dụng application/x-www-form-urlencodedloại nội dung:

using (var client = new WebClient())
{
    var values = new NameValueCollection
    {
        { "param1", "value1" },
        { "param2", "value2" },
    };
    var result = client.UploadValues("http://foo.com", values);
}


-3
System.Net.WebUtility.HtmlDecode

Lớp WebUtility cung cấp các phương thức để mã hóa và giải mã URL khi xử lý các yêu cầu Web. Nó thực hiện tương tự như HTTPUtility nhưng nó nằm ngoài không gian tên System.Web
Alexandru Aliu

3
Điều đó sai vì nó là HtmlDecodes và không UrlEncode như câu hỏi được hỏi. Ngay cả HtmlEncode cũng sẽ sai vì mã hóa HTML khác với mã hóa URL.
Martin Brown
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.