Jak zrobić UrlEncode bez korzystania z System.Web?


310

Usiłuję napisać aplikację kliencką dla systemu Windows, która wywołuje witrynę z danymi. Aby ograniczyć instalację do minimum, próbuję używać tylko bibliotek dll w profilu klienta .NET Framework . Problem w tym, że muszę UrlEncode niektórych parametrów. Czy istnieje prosty sposób, aby to zrobić bez importowania pliku System.Web.dll, który nie jest częścią pliku Pofile klienta?


Czy możesz pokazać, w jaki sposób wykonujesz połączenie z witryną? Może jest coś, co można tam zrobić.
— Darin Dimitrov

Z ciekawości, jak wywołać witrynę internetową dla danych bez korzystania z System.Web?
— Patrick McDonald

@Pickick, prawdopodobnie używa WebRequestlub WebClient. To jest powód, dla którego zapytałem o ten konkretny kod, ponieważ są pewne rzeczy, które można zrobić w kwestii poprawnego kodowania danych URL.
— Darin Dimitrov

1
Używam obiektu System.Net.WebRequest. Następnie wywołuję GetRequestStream i zapisuję parametry Post do strumienia. Ustawiłem także ContentType na „application / x-www-form-urlencoded”.
— Martin Brown

1
Oczywiście to samo dotyczyłoby, gdybym wykonywał żądanie GET i dołączał parametry do adresu URL.
— Martin Brown

Odpowiedzi:


317

System.Uri.EscapeUriString() może być problematyczne z niektórymi znakami, dla mnie był to znak liczby / funta „#” w ciągu.

Jeśli jest to dla Ciebie problem, spróbuj:

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

Oto odpowiedź na pytanie SO, która wyjaśnia różnicę:

Jaka jest różnica między EscapeUriString i EscapeDataString?

i zaleca stosowanie Uri.EscapeDataString()w dowolnym aspekcie.


1
Fałsz: blogs.msdn.com/b/yangxind/archive/2006/11/09/… Będziesz mieć problemy ze znakami plus, ponieważ nie zostaną one zakodowane.
— Chris Weber,

7
Ten post na blogu jest nieco stary i po prostu mam pełny adres URL „Uri Escaped”, a wszystkie spacje stały się% 20, więc myślę, że to naprawili. Używam .Net 4.5.
— Rodi

EscapeDataString nie obsługuje również bardzo długich ciągów, jeśli przygotowujesz dane do operacji POST. stackoverflow.com/questions/6695208/...
— Bron Davies,

Uri.EscapeUriStringjest rzeczywiście bardzo problematyczny i nie należy go stosować, ponieważ próbuje on zrobić coś (unikając pełnych identyfikatorów URI), co jest w rzeczywistości niemożliwe do konsekwentnego wykonania. Zobacz tę odpowiedź, aby uzyskać szczegółowe wyjaśnienie.
— Livven,

Również postać spacji.
— Waqas Shabbir

252

W użyciu .Net 4.5+ WebUtility

Tylko do sformatowania przesyłam to jako odpowiedź.

Nie udało mi się znaleźć dobrych przykładów porównujących je, więc:

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));

Wyjścia:

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

W użyciu .Net 4.5+ WebUtility.UrlEncode

Wygląda na to, że replikuje się HttpUtility.UrlEncode(w wersjach wcześniejszych niż 4.0) w przypadku bardziej powszechnych znaków:
Uri.EscapeDataString(testString).Replace("%20", "+").Replace("'", "%27").Replace("~", "%7E")
Uwaga: EscapeUriStringzachowa prawidłowy ciąg znaków uri, co powoduje, że używa jak największej liczby znaków w postaci zwykłego tekstu.

Zobacz odpowiedź na tabelę porównującą różne kodowania:
https://stackoverflow.com/a/11236038/555798

Podziały linii Wszystkie wymienione tutaj (inne niż HttpUtility.HtmlEncode) zostaną zamienione "\n\r"na %0a%0dlub%0A%0D

Zmodyfikuj to i dodaj nowe znaki do mojego ciągu testowego lub zostaw je w komentarzach, a ja je wyedytuję.


W moim przypadku musiałem użyć EscapeDataStringzamiast EscapeUriStringkodowania powrotów karetki i linii, a to wymagało bardziej agresywnego ucieczki, którego dokonałEscapeDataString
— David O'Meara,

1
więcej przykładów, jeśli chcesz, możesz podać własne przypadki testowe. Oto próbka jego uruchomienia i innych metod kodowania, które pokazują różnice dotnetfiddle.net/12IFw1
— Maslow

3
WebUtility.UrlEncode () i WebUtility.UrlDecode () to 4.5+. Nie istnieją w 4.0.
— Derek Kalweit,

Msdn mówi: „Uniwersalna platforma Windows: dostępna od 4.5, .NET Framework: dostępna od 4.0” ...
— Thymine

54

Czy istnieje różnica między tym a EscapeDataString?
— Martin Brown

3
Chcesz użyć EscapeUriString. EscapeUriString spróbuje zakodować cały adres URL (w tym http: // część), podczas gdy EscapeUriString zrozumie, które części powinny zostać zakodowane
— Matthew Manela

1
Rozumiem, więc w tym przypadku prawdopodobnie chciałbym EscapeDataString, ponieważ mogę przekazać adres URL jako parametr get. W tym przypadku dołączam do adresu URL.
— Martin Brown

5
@MatthewManela Jestem pewien, że Twój komentarz z października powinien brzmieć EscapeDataString spróbuje zakodować ...
— Maslow

Nie używać Uri.EscapeUriString. Nie „rozumie”, jakie części należy zakodować, jest to po prostu błędna próba zrobienia czegoś (unikanie pełnych identyfikatorów URI), co w rzeczywistości jest niemożliwe do konsekwentnego wykonania. Zobacz tę odpowiedź, aby uzyskać szczegółowe wyjaśnienie.
— Livven,

20

Odpowiedzi tutaj są bardzo dobre, ale wciąż dla mnie niewystarczające.

Napisałem małą pętlę, który porównuje Uri.EscapeUriStringsię Uri.EscapeDataStringdo wszystkich znaków od 0 do 255.

UWAGA: Obie funkcje mają wbudowaną inteligencję, że znaki powyżej 0x80 są najpierw kodowane UTF-8, a następnie procentowo.

Oto wynik:

******* 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"
.....

EscapeUriStringma być używany do kodowania adresów URL, podczas gdy EscapeDataStringma być używany do kodowania na przykład zawartości pliku cookie, ponieważ dane plików cookie nie mogą zawierać znaków zastrzeżonych '='i ';'.


miła analiza i podział tutaj, bardzo pomocne. jeśli ktoś ma lub zna wzorce wydajności (porównując wszystkie trzy metody), również miło byłoby je zobaczyć
— Shaun Wilson

To dobra analiza, a na wynos nie należy jej używać Uri.EscapeUriString, ponieważ unikanie pełnych identyfikatorów URI jest niemożliwe. Zobacz tę odpowiedź, aby uzyskać szczegółowe wyjaśnienie.
— Livven,

16

Istnieje wersja użyteczna profilu klienta, klasa System.Net.WebUtility, obecna w profilu klienta System.dll. Oto link MSDN:

WebUtility


Zwracam uwagę, że strona pomocy dla tej klasy wyraźnie mówi „Zapewnia metody kodowania i dekodowania adresów URL podczas przetwarzania żądań internetowych”. więc może być tak, że nie nazwali dobrze metod.
— James White

Dobra uwaga, powiedz, dlaczego nie głosujesz na brata w górę;) ten głos w dół prześladuje mnie od 2 lat! JK ... ale szczerze mówiąc prawdopodobnie dlatego opublikowałem link, niefortunnie, że biorę reputację za błędy w dokumentach Microsoftu ...
— Sprague

11
Wygląda na to, że UrlEncode i UrlDecode zostały dodane do WebUtility tylko w wersji 4.5 .Net.
— Martin Brown

8

Oto przykład wysłania żądania POST, które poprawnie koduje parametry przy użyciu application/x-www-form-urlencodedtypu zawartości:

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

Klasa WebUtility zapewnia metody kodowania i dekodowania adresów URL podczas przetwarzania żądań internetowych. Robi to samo co HttpUtility, ale jest poza przestrzenią nazw System.Web
— Alexandru Aliu

3
Jest źle, ponieważ kod HtmlDecodes i nie koduje UrlEncode jak zadane pytanie. Nawet HtmlEncode byłoby błędne, ponieważ kodowanie HTML różni się od kodowania URL.
— Martin Brown
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.