Kodowanie URL przy użyciu C #

340

Mam aplikację, która wysyła żądanie POST do oprogramowania forum VB i loguje kogoś (bez ustawiania plików cookie lub czegokolwiek).

Po zalogowaniu się użytkownika tworzę zmienną, która tworzy ścieżkę na ich komputerze lokalnym.

c: \ tempfolder \ date \ nazwa użytkownika

Problem polega na tym, że niektóre nazwy użytkowników zgłaszają wyjątek „Nielegalne znaki”. Na przykład, jeśli moja nazwa użytkownika mas|fenixto zgłasza wyjątek.

Path.Combine( _      
  Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData), _
  DateTime.Now.ToString("ddMMyyhhmm") + "-" + form1.username)

Nie chcę go usuwać z ciągu, ale folder z nazwą użytkownika jest tworzony za pośrednictwem FTP na serwerze. To prowadzi do mojego drugiego pytania. Jeśli tworzę folder na serwerze, czy mogę pozostawić „nielegalne znaki” w? Pytam tylko o to, ponieważ serwer jest oparty na systemie Linux i nie jestem pewien, czy Linux to akceptuje, czy nie.

EDYCJA: Wygląda na to, że kodowanie adresu URL NIE jest tym, czego chcę. Oto, co chcę zrobić:

old username = mas|fenix
new username = mas%xxfenix

Gdzie% xx to wartość ASCII lub dowolna inna wartość, która łatwo identyfikowałaby znak.

masfenix
źródło
Włącz to, aby nazwy folderów systemu plików były bezpieczne: http://stackoverflow.com/questions/333175/is-there-a-way-of-making-strings-file-path-safe-in-c
missaghi

Odpowiedzi:

191

Edycja: pamiętaj, że ta odpowiedź jest nieaktualna. Zobacz odpowiedź Siarhiej Kuchuk jest poniżej dla lepszego fix

UrlEncoding zrobi to, co tutaj sugerujesz. Z C # po prostu używasz HttpUtility, jak wspomniano.

Możesz także ponownie Zexeksować niedozwolone znaki, a następnie zamienić, ale staje się to o wiele bardziej skomplikowane, ponieważ będziesz musiał mieć jakąś formę automatu stanów (na przykład zmień ... obudowę), aby zastąpić prawidłowymi znakami. Ponieważ UrlEncoderobi to z góry, jest to raczej łatwe.

Jeśli chodzi o Linux kontra Windows, niektóre znaki są akceptowane w Linuksie, ale nie są w systemie Windows, ale nie martwiłbym się tym, ponieważ nazwę folderu można zwrócić, dekodując ciąg adresu URL, używając UrlDecode, aby można było przejść w obie strony zmiany.

Gregory A Beamer
źródło
5
ta odpowiedź jest już nieaktualna. przeczytaj kilka odpowiedzi poniżej - od .net45 może to być poprawne rozwiązanie: msdn.microsoft.com/en-us/library/…
blueberryfields
1
W przypadku FTP każdą część Uri (nazwę folderu lub pliku) można skonstruować za pomocą Uri.EscapeDataString (fileOrFolderName), dopuszczając wszystkie znaki niekompatybilne z Uri (spacje, Unicode ...). Na przykład, aby zezwolić na dowolny znak w nazwie pliku, użyj: req = (FtpWebRequest) WebRequest.Create (nowy Uri (ścieżka + "/" + Uri.EscapeDataString (nazwa pliku))); Za pomocą HttpUtility.UrlEncode () zamień spacje na znaki plus (+). Prawidłowe zachowanie wyszukiwarek, ale niepoprawne dla nazw plików / folderów.
Renaud Bancel
asp.net blokuje większość xss w adresie URL, gdy pojawia się ostrzeżenie przy każdej próbie dodania skryptu js A potentially dangerous Request.Path value was detected from the client.
Nauka
510

Eksperymentowałem z różnymi metodami .NET zapewniającymi kodowanie adresów URL. Być może przydatna będzie poniższa tabela (jako wynik z aplikacji testowej, którą napisałem):

Unencoded UrlEncoded UrlEncodedUnicode UrlPathEncoded EscapedDataString EscapedUriString HtmlEncoded HtmlAttributeEncoded HexEscaped
A         A          A                 A              A                 A                A           A                    %41
B         B          B                 B              B                 B                B           B                    %42

a         a          a                 a              a                 a                a           a                    %61
b         b          b                 b              b                 b                b           b                    %62

0         0          0                 0              0                 0                0           0                    %30
1         1          1                 1              1                 1                1           1                    %31

[space]   +          +                 %20            %20               %20              [space]     [space]              %20
!         !          !                 !              !                 !                !           !                    %21
"         %22        %22               "              %22               %22              "      "               %22
#         %23        %23               #              %23               #                #           #                    %23
$         %24        %24               $              %24               $                $           $                    %24
%         %25        %25               %              %25               %25              %           %                    %25
&         %26        %26               &              %26               &                &       &                %26
'         %27        %27               '              '                 '                '       '                %27
(         (          (                 (              (                 (                (           (                    %28
)         )          )                 )              )                 )                )           )                    %29
*         *          *                 *              %2A               *                *           *                    %2A
+         %2b        %2b               +              %2B               +                +           +                    %2B
,         %2c        %2c               ,              %2C               ,                ,           ,                    %2C
-         -          -                 -              -                 -                -           -                    %2D
.         .          .                 .              .                 .                .           .                    %2E
/         %2f        %2f               /              %2F               /                /           /                    %2F
:         %3a        %3a               :              %3A               :                :           :                    %3A
;         %3b        %3b               ;              %3B               ;                ;           ;                    %3B
<         %3c        %3c               <              %3C               %3C              &lt;        &lt;                 %3C
=         %3d        %3d               =              %3D               =                =           =                    %3D
>         %3e        %3e               >              %3E               %3E              &gt;        >                    %3E
?         %3f        %3f               ?              %3F               ?                ?           ?                    %3F
@         %40        %40               @              %40               @                @           @                    %40
[         %5b        %5b               [              %5B               %5B              [           [                    %5B
\         %5c        %5c               \              %5C               %5C              \           \                    %5C
]         %5d        %5d               ]              %5D               %5D              ]           ]                    %5D
^         %5e        %5e               ^              %5E               %5E              ^           ^                    %5E
_         _          _                 _              _                 _                _           _                    %5F
`         %60        %60               `              %60               %60              `           `                    %60
{         %7b        %7b               {              %7B               %7B              {           {                    %7B
|         %7c        %7c               |              %7C               %7C              |           |                    %7C
}         %7d        %7d               }              %7D               %7D              }           }                    %7D
~         %7e        %7e               ~              ~                 ~                ~           ~                    %7E

Ā         %c4%80     %u0100            %c4%80         %C4%80            %C4%80           Ā           Ā                    [OoR]
ā         %c4%81     %u0101            %c4%81         %C4%81            %C4%81           ā           ā                    [OoR]
Ē         %c4%92     %u0112            %c4%92         %C4%92            %C4%92           Ē           Ē                    [OoR]
ē         %c4%93     %u0113            %c4%93         %C4%93            %C4%93           ē           ē                    [OoR]
Ī         %c4%aa     %u012a            %c4%aa         %C4%AA            %C4%AA           Ī           Ī                    [OoR]
ī         %c4%ab     %u012b            %c4%ab         %C4%AB            %C4%AB           ī           ī                    [OoR]
Ō         %c5%8c     %u014c            %c5%8c         %C5%8C            %C5%8C           Ō           Ō                    [OoR]
ō         %c5%8d     %u014d            %c5%8d         %C5%8D            %C5%8D           ō           ō                    [OoR]
Ū         %c5%aa     %u016a            %c5%aa         %C5%AA            %C5%AA           Ū           Ū                    [OoR]
ū         %c5%ab     %u016b            %c5%ab         %C5%AB            %C5%AB           ū           ū                    [OoR]

Kolumny przedstawiają kodowanie w następujący sposób:

  • UrlEncoded: HttpUtility.UrlEncode

  • UrlEncodedUnicode: HttpUtility.UrlEncodeUnicode

  • UrlPathEncoded: HttpUtility.UrlPathEncode

  • EscapedDataString: Uri.EscapeDataString

  • EscapedUriString: Uri.EscapeUriString

  • HtmlEncoded: HttpUtility.HtmlEncode

  • HtmlAttributeEncoded: HttpUtility.HtmlAttributeEncode

  • HexEscaped: Uri.HexEscape

UWAGI:

  1. HexEscapeobsługuje tylko pierwsze 255 znaków. Dlatego zgłasza ArgumentOutOfRangewyjątek dla znaków Latin A-Extended (np. Ā).

  2. Ta tabela została wygenerowana w .NET 4.0 (patrz komentarz Levi Botelho poniżej, który mówi, że kodowanie w .NET 4.5 jest nieco inne).

EDYTOWAĆ:

Dodałem drugą tabelę z kodowaniem dla .NET 4.5. Zobacz tę odpowiedź: https://stackoverflow.com/a/21771206/216440

EDYCJA 2:

Ponieważ ludzie wydają się doceniać te stoły, pomyślałem, że może ci się spodobać kod źródłowy, który generuje ten stół, abyś mógł bawić się wokół siebie. Jest to prosta aplikacja konsoli C #, która może być ukierunkowana na .NET 4.0 lub 4.5:

using System;
using System.Collections.Generic;
using System.Text;
// Need to add a Reference to the System.Web assembly.
using System.Web;

namespace UriEncodingDEMO2
{
    class Program
    {
        static void Main(string[] args)
        {
            EncodeStrings();

            Console.WriteLine();
            Console.WriteLine("Press any key to continue...");
            Console.Read();
        }

        public static void EncodeStrings()
        {
            string stringToEncode = "ABCD" + "abcd"
            + "0123" + " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" + "ĀāĒēĪīŌōŪū";

            // Need to set the console encoding to display non-ASCII characters correctly (eg the 
            //  Latin A-Extended characters such as ĀāĒē...).
            Console.OutputEncoding = Encoding.UTF8;

            // Will also need to set the console font (in the console Properties dialog) to a font 
            //  that displays the extended character set correctly.
            // The following fonts all display the extended characters correctly:
            //  Consolas
            //  DejaVu Sana Mono
            //  Lucida Console

            // Also, in the console Properties, set the Screen Buffer Size and the Window Size 
            //  Width properties to at least 140 characters, to display the full width of the 
            //  table that is generated.

            Dictionary<string, Func<string, string>> columnDetails =
                new Dictionary<string, Func<string, string>>();
            columnDetails.Add("Unencoded", (unencodedString => unencodedString));
            columnDetails.Add("UrlEncoded",
                (unencodedString => HttpUtility.UrlEncode(unencodedString)));
            columnDetails.Add("UrlEncodedUnicode",
                (unencodedString => HttpUtility.UrlEncodeUnicode(unencodedString)));
            columnDetails.Add("UrlPathEncoded",
                (unencodedString => HttpUtility.UrlPathEncode(unencodedString)));
            columnDetails.Add("EscapedDataString",
                (unencodedString => Uri.EscapeDataString(unencodedString)));
            columnDetails.Add("EscapedUriString",
                (unencodedString => Uri.EscapeUriString(unencodedString)));
            columnDetails.Add("HtmlEncoded",
                (unencodedString => HttpUtility.HtmlEncode(unencodedString)));
            columnDetails.Add("HtmlAttributeEncoded",
                (unencodedString => HttpUtility.HtmlAttributeEncode(unencodedString)));
            columnDetails.Add("HexEscaped",
                (unencodedString
                    =>
                    {
                        // Uri.HexEscape can only handle the first 255 characters so for the 
                        //  Latin A-Extended characters, such as A, it will throw an 
                        //  ArgumentOutOfRange exception.                       
                        try
                        {
                            return Uri.HexEscape(unencodedString.ToCharArray()[0]);
                        }
                        catch
                        {
                            return "[OoR]";
                        }
                    }));

            char[] charactersToEncode = stringToEncode.ToCharArray();
            string[] stringCharactersToEncode = Array.ConvertAll<char, string>(charactersToEncode,
                (character => character.ToString()));
            DisplayCharacterTable<string>(stringCharactersToEncode, columnDetails);
        }

        private static void DisplayCharacterTable<TUnencoded>(TUnencoded[] unencodedArray,
            Dictionary<string, Func<TUnencoded, string>> mappings)
        {
            foreach (string key in mappings.Keys)
            {
                Console.Write(key.Replace(" ", "[space]") + " ");
            }
            Console.WriteLine();

            foreach (TUnencoded unencodedObject in unencodedArray)
            {
                string stringCharToEncode = unencodedObject.ToString();
                foreach (string columnHeader in mappings.Keys)
                {
                    int columnWidth = columnHeader.Length + 1;
                    Func<TUnencoded, string> encoder = mappings[columnHeader];
                    string encodedString = encoder(unencodedObject);

                    // ASSUMPTION: Column header will always be wider than encoded string.
                    Console.Write(encodedString.Replace(" ", "[space]").PadRight(columnWidth));
                }
                Console.WriteLine();
            }
        }
    }
}
Simon Tewsi
źródło
2
To fantastyczna odpowiedź. Okazało się, że chciałem użyć Uri.EscapeDataString, a nie dołączyć System.Web. Dzięki za ten stół.
Seravy,
7
Pamiętaj, że nie jest to już w 100% dokładne. Niektóre funkcje zmieniły się nieznacznie między .NET 4 i .NET 4.5. Zobacz stackoverflow.com/q/20003106/1068266 .
Levi Botelho
2
@Levi: Dzięki za zgłoszenie się. Dodałem drugą odpowiedź z tabelą dla .NET 4.5. Zredagowałem oryginalną odpowiedź na link do drugiej tabeli.
Simon Tewsi
Zauważ, że w dokumentacji .NET jest napisane: Nie używaj; przeznaczony tylko do kompatybilności z przeglądarkami. Użyj UrlEncode. , ale ta metoda koduje wiele innych niepożądanych znaków. Najbliższa jest Uri.EscapeUriString, ale uwaga: nie obsługuje nullargumentu.
Andrew
1
Zapomniałem wspomnieć, mój komentarz powyżej dotyczy UrlPathEncode. Więc w zasadzie zastąpić UrlPathEncodez Uri.EscapeUriString.
Andrew
278

Powinieneś zakodować tylko nazwę użytkownika lub inną część adresu URL, która może być nieprawidłowa. Kodowanie adresu URL może prowadzić do problemów, ponieważ coś takiego:

string url = HttpUtility.UrlEncode("http://www.google.com/search?q=Example");

Ustąpi

http% 3a% 2f% 2fwww.google.com% 2fsearch% 3fq% 3dPrzykład

To oczywiście nie zadziała dobrze. Zamiast tego należy zakodować TYLKO wartość pary klucz / wartość w ciągu zapytania, tak jak poniżej:

string url = "http://www.google.com/search?q=" + HttpUtility.UrlEncode("Example");

Mam nadzieję, że to pomaga. Ponadto, jak wspomniano w teedyay , nadal musisz upewnić się, że znaki nielegalnej nazwy pliku zostały usunięte, w przeciwnym razie systemowi plików nie spodoba się ścieżka.

Dan Herbert
źródło
33
Zastosowanie metody HttpUtility.UrlPathEncode powinno zapobiec opisywanemu tutaj problemowi.
vipirtti
12
@DJ Pirtu: To prawda, że ​​UrlPathEncode nie dokona tych niepożądanych zmian na ścieżce, jednak nie zakoduje też niczego po ?(ponieważ zakłada, że ​​ciąg zapytania jest już zakodowany). W przykładzie Dana Herberta wygląda na to, że udaje, Exampleże tekst wymaga kodowania, więc HttpUtility.UrlPathEncode("http://www.google.com/search?q=Example");nie będzie działać. Wypróbuj z ?q=Ex&ple(tam, gdzie jest pożądany wynik ?q=Ex%26ple). Nie zadziała, ponieważ (1) UrlPathEncode nie dotyka niczego później ?, a (2) UrlPathEncode i tak nie koduje &.
Tim Goodman
1
Zobacz tutaj: connect.microsoft.com/VisualStudio/feedback/details/551839/ ... Powinienem dodać, że oczywiście dobrze, że UrlPathEncode nie koduje &, ponieważ potrzebujesz go do ograniczenia parametrów ciągu zapytania. Ale są chwile, kiedy chcesz także zakodowane znaki handlowe.
Tim Goodman
10
HttpUtility został zastąpiony przez WebUtility w najnowszych wersjach, oszczędź sobie trochę czasu :)
Wiseman
190

Lepszym sposobem jest użycie

Uri.EscapeUriString

nie odwoływać się do pełnego profilu .net 4.

Siarhei Kuchuk
źródło
1
Całkowicie się zgadzam, ponieważ często „profil klienta” wystarcza dla aplikacji korzystających z System.Net, ale nie korzystających z System.Web ;-)
hfrmobile
6
OP mówi o sprawdzeniu zgodności systemu plików, więc to nie zadziała. Zestaw znaków niedozwolonych w systemie Windows to „[” / ”,„ \\ ”,„ <”,„> ”,„: ”,„ \ ””, „|”, „?”, „*”] ”, Ale wiele z nich nie koduj za pomocą EscapedUriString (patrz tabela poniżej - dzięki za tę tabelę @ Simon Tewsi) ... „tworzy ścieżkę na lokalnej maszynie” -OP UrlEncoded zajmuje się prawie wszystkimi problemami, ale nie rozwiązuje problem z „%” lub „% 3f” znajdującymi się na oryginalnym wejściu, ponieważ „dekodowanie” będzie teraz inne niż oryginalne.
m1m1k
6
żeby było jasne: ta odpowiedź NIE DZIAŁA dla systemów plików
m1m1k
1
Ponadto, począwszy od .NET Framework 4.5, profil klienta został wycofany i dostępny jest tylko pełny pakiet redystrybucyjny.
twomm
29
stackoverflow.com/a/34189188/3436164 Użyj Uri.EscapeDataStringNIE Uri.EscapeUriStringPrzeczytaj ten komentarz, pomógł mi.
ykadaru
181

Od .NET Framework 4.5 i .NET Standard 1.0 powinieneś używać WebUtility.UrlEncode. Zalety w porównaniu z alternatywami:

  1. Jest częścią .NET Framework 4.5+, .NET Core 1.0+, .NET Standard 1.0+, UWP 10.0+ oraz wszystkich platform Xamarin. HttpUtility, chociaż jest wcześniej dostępny w .NET Framework (.NET Framework 1.1+), staje się dostępny na innych platformach znacznie później (.NET Core 2.0+, .NET Standard 2.0+) i nadal nie jest dostępny w UWP (patrz powiązane pytanie ).

  2. W .NET Framework znajduje się w nimSystem.dll , więc nie wymaga żadnych dodatkowych odniesień, w przeciwieństwie do HttpUtility.

  3. W odróżnieniu od tego poprawnie zmienia znaki dla adresów URLUri.EscapeUriString (patrz komentarze do odpowiedzi drweb86 ).

  4. W przeciwieństwie do (patrz powiązane pytanie ) nie ma żadnych ograniczeń długości łańcucha , więc można go na przykład użyć do żądań POST.Uri.EscapeDataString

Athari
źródło
Podoba mi się sposób, w jaki koduje za pomocą „+” zamiast% 20 dla spacji .. ale ten nadal nie usuwa „z adresu URL i daje mi nieprawidłowy adres URL ... no cóż ... po prostu będę musiał dokonać zamiany („ „” „”, „”)
Piotr Kula
84

Levi Botelho skomentował, że wcześniej wygenerowana tabela kodowań nie jest już dokładna dla .NET 4.5, ponieważ kodowania zmieniły się nieznacznie między .NET 4.0 i 4.5. Ponownie wygenerowałem tabelę dla .NET 4.5:

Unencoded UrlEncoded UrlEncodedUnicode UrlPathEncoded WebUtilityUrlEncoded EscapedDataString EscapedUriString HtmlEncoded HtmlAttributeEncoded WebUtilityHtmlEncoded HexEscaped
A         A          A                 A              A                    A                 A                A           A                    A                     %41
B         B          B                 B              B                    B                 B                B           B                    B                     %42

a         a          a                 a              a                    a                 a                a           a                    a                     %61
b         b          b                 b              b                    b                 b                b           b                    b                     %62

0         0          0                 0              0                    0                 0                0           0                    0                     %30
1         1          1                 1              1                    1                 1                1           1                    1                     %31

[space]   +          +                 %20            +                    %20               %20              [space]     [space]              [space]               %20
!         !          !                 !              !                    %21               !                !           !                    !                     %21
"         %22        %22               "              %22                  %22               %22              &quot;      &quot;               &quot;                %22
#         %23        %23               #              %23                  %23               #                #           #                    #                     %23
$         %24        %24               $              %24                  %24               $                $           $                    $                     %24
%         %25        %25               %              %25                  %25               %25              %           %                    %                     %25
&         %26        %26               &              %26                  %26               &                &amp;       &amp;                &amp;                 %26
'         %27        %27               '              %27                  %27               '                &#39;       &#39;                &#39;                 %27
(         (          (                 (              (                    %28               (                (           (                    (                     %28
)         )          )                 )              )                    %29               )                )           )                    )                     %29
*         *          *                 *              *                    %2A               *                *           *                    *                     %2A
+         %2b        %2b               +              %2B                  %2B               +                +           +                    +                     %2B
,         %2c        %2c               ,              %2C                  %2C               ,                ,           ,                    ,                     %2C
-         -          -                 -              -                    -                 -                -           -                    -                     %2D
.         .          .                 .              .                    .                 .                .           .                    .                     %2E
/         %2f        %2f               /              %2F                  %2F               /                /           /                    /                     %2F
:         %3a        %3a               :              %3A                  %3A               :                :           :                    :                     %3A
;         %3b        %3b               ;              %3B                  %3B               ;                ;           ;                    ;                     %3B
<         %3c        %3c               <              %3C                  %3C               %3C              &lt;        &lt;                 &lt;                  %3C
=         %3d        %3d               =              %3D                  %3D               =                =           =                    =                     %3D
>         %3e        %3e               >              %3E                  %3E               %3E              &gt;        >                    &gt;                  %3E
?         %3f        %3f               ?              %3F                  %3F               ?                ?           ?                    ?                     %3F
@         %40        %40               @              %40                  %40               @                @           @                    @                     %40
[         %5b        %5b               [              %5B                  %5B               [                [           [                    [                     %5B
\         %5c        %5c               \              %5C                  %5C               %5C              \           \                    \                     %5C
]         %5d        %5d               ]              %5D                  %5D               ]                ]           ]                    ]                     %5D
^         %5e        %5e               ^              %5E                  %5E               %5E              ^           ^                    ^                     %5E
_         _          _                 _              _                    _                 _                _           _                    _                     %5F
`         %60        %60               `              %60                  %60               %60              `           `                    `                     %60
{         %7b        %7b               {              %7B                  %7B               %7B              {           {                    {                     %7B
|         %7c        %7c               |              %7C                  %7C               %7C              |           |                    |                     %7C
}         %7d        %7d               }              %7D                  %7D               %7D              }           }                    }                     %7D
~         %7e        %7e               ~              %7E                  ~                 ~                ~           ~                    ~                     %7E

Ā         %c4%80     %u0100            %c4%80         %C4%80               %C4%80            %C4%80           Ā           Ā                    Ā                     [OoR]
ā         %c4%81     %u0101            %c4%81         %C4%81               %C4%81            %C4%81           ā           ā                    ā                     [OoR]
Ē         %c4%92     %u0112            %c4%92         %C4%92               %C4%92            %C4%92           Ē           Ē                    Ē                     [OoR]
ē         %c4%93     %u0113            %c4%93         %C4%93               %C4%93            %C4%93           ē           ē                    ē                     [OoR]
Ī         %c4%aa     %u012a            %c4%aa         %C4%AA               %C4%AA            %C4%AA           Ī           Ī                    Ī                     [OoR]
ī         %c4%ab     %u012b            %c4%ab         %C4%AB               %C4%AB            %C4%AB           ī           ī                    ī                     [OoR]
Ō         %c5%8c     %u014c            %c5%8c         %C5%8C               %C5%8C            %C5%8C           Ō           Ō                    Ō                     [OoR]
ō         %c5%8d     %u014d            %c5%8d         %C5%8D               %C5%8D            %C5%8D           ō           ō                    ō                     [OoR]
Ū         %c5%aa     %u016a            %c5%aa         %C5%AA               %C5%AA            %C5%AA           Ū           Ū                    Ū                     [OoR]
ū         %c5%ab     %u016b            %c5%ab         %C5%AB               %C5%AB            %C5%AB           ū           ū                    ū                     [OoR]

Kolumny przedstawiają kodowanie w następujący sposób:

  • UrlEncoded: HttpUtility.UrlEncode
  • UrlEncodedUnicode: HttpUtility.UrlEncodeUnicode
  • UrlPathEncoded: HttpUtility.UrlPathEncode
  • WebUtilityUrlEncoded: WebUtility.UrlEncode
  • EscapedDataString: Uri.EscapeDataString
  • EscapedUriString: Uri.EscapeUriString
  • HtmlEncoded: HttpUtility.HtmlEncode
  • HtmlAttributeEncoded: HttpUtility.HtmlAttributeEncode
  • WebUtilityHtmlEncoded: WebUtility.HtmlEncode
  • HexEscaped: Uri.HexEscape

UWAGI:

  1. HexEscape obsługuje tylko pierwsze 255 znaków. Dlatego zgłasza wyjątek ArgumentOutOfRange dla znaków Latin A-Extended (np. Ā).

  2. Ta tabela została wygenerowana w .NET 4.5 (patrz kodowanie https://stackoverflow.com/a/11236038/216440 dla kodowań odpowiednich dla .NET 4.0 i niższych).

EDYTOWAĆ:

  1. W wyniku odpowiedzi Discorda dodałem nowe metody WebUtility UrlEncode i HtmlEncode, które zostały wprowadzone w .NET 4.5.
Simon Tewsi
źródło
2
Nie, nie użytkownik UrlPathEncode - nawet MSDN mówi, że nie należy go używać. Zostało zbudowane, aby naprawić problem z netscape 2 msdn.microsoft.com/en-us/library/…
Jeff
Czy Server.URLEncode to kolejna odmiana tego motywu? Czy generuje jakieś inne wyniki?
ALEXintlsos,
2
@ALEX: W ASP.NET obiekt serwera jest instancją HttpServerUtility. Używając dekompilatora dotPeek przyjrzałem się HttpServerUtility.UrlEncode. Po prostu wywołuje HttpUtility.UrlEncode, aby wynik obu metod był identyczny.
Simon Tewsi,
Wygląda na to, że nawet przy tej nadmiarze metod kodowania wszystkie one nadal zawodzą dość spektakularnie w przypadku elementów powyżej Latin-1, takich jak → lub ☠. (UrlEncodedUnicode wydaje się, że przynajmniej próbuje obsługiwać Unicode, ale jest przestarzały / brakuje go).
brianary
Simon, czy możesz po prostu włączyć tę odpowiedź do zaakceptowanej odpowiedzi? miło będzie mieć go w jednej odpowiedzi. możesz to zintegrować i zrobić nagłówek h1 na dole tej odpowiedzi lub zintegrować w jednej tabeli i oznaczyć różne wiersze, np .: (Net4.0) ? %3f................................ (Net4.5) ? %3f ..................................
T.Todua
60

Kodowanie adresów URL jest łatwe w .NET. Posługiwać się:

System.Web.HttpUtility.UrlEncode(string url)

Jeśli zostanie to zdekodowane w celu uzyskania nazwy folderu, nadal musisz wykluczyć znaki, których nie można użyć w nazwach folderów (*,?, / Itd.)

teedyay
źródło
Czy koduje każdy znak, który nie jest częścią alfabetu?
masfenix
1
Kodowanie URL konwertuje znaki, które nie są dozwolone w adresie URL, na ekwiwalenty encji znakowej. Lista niebezpiecznych znaków: blooberry.com/indexdot/html/topics/urlencoding.htm
Ian Robinson
Link MSDN na HttpUtility.UrlEncode: msdn.microsoft.com/en-us/library/4fkewx0t.aspx
Ian Robinson
11
Dobrą praktyką jest umieszczenie pełnego System.Web ... w odpowiedzi, oszczędza to trochę czasu :) dzięki
Liam
3
Jest to niebezpieczne: nie wszystkie znaki adresu URL muszą być zakodowane, tylko wartości parametrów kwerendy. Sposób, w jaki sugerujesz, koduje także &, który jest potrzebny do utworzenia wielu parametrów w querystring. W razie potrzeby
soution
12

Jeśli nie widzisz System.Web, zmień ustawienia projektu. Docelową strukturą powinna być „.NET Framework 4” zamiast „.NET Framework 4 Client Profile”

przydatny
źródło
1
Moim zdaniem programiści powinni wiedzieć o „profilach .NET” i powinni używać właściwego do swoich celów! Po prostu dodanie pełnego profilu, aby uzyskać (np. System.Web), nie bardzo wiedząc, dlaczego dodają pełny profil, nie jest zbyt mądre. Użyj „Profilu klienta” dla aplikacji klienckich i pełnego profilu tylko w razie potrzeby (np. Klient WinForms lub WPF powinien używać profilu klienta, a nie pełnego profilu)! np. nie widzę powodu, aby używać HttpServerUtility w aplikacji klienckiej ^^ ... jeśli jest to potrzebne, to jest coś nie tak z projektem aplikacji!
hfrmobile
4
Naprawdę? Czy nigdy nie widzisz potrzeby, aby aplikacja kliencka tworzyła adres URL? Co robisz dla życia - obowiązki porządkowe?
sproketboy
@hfrmobile: no. Wszystko jest nie tak z modelem profilu (który żył tylko raz i został porzucony w następnej wersji). I to było oczywiste od samego początku. Czy to teraz dla ciebie oczywiste? Najpierw pomyśl, nie akceptuj wszystkiego „tak, jak jest”, co msft próbuje ci sprzedać; P
abatishchev
Przykro mi, ale nigdy nie powiedziałem, że klient nigdy nie musi budować / używać adresu URL. Tak długo, jak działa .NET 4.0, użytkownik powinien się tym przejmować. Krótko mówiąc: programiści powinni pomyśleć dwa razy, zanim dodadzą HttpServerUtility do klienta. Są inne / lepsze sposoby, wystarczy zobaczyć odpowiedź ze 139 głosami lub „Od .NET Framework 4.5 możesz użyć WebUtility.UrlEncode. Po pierwsze, znajduje się w System.dll, więc nie wymaga żadnych dodatkowych odniesień.”.
hfrmobile
9

Implementacja .NET UrlEncodenie jest zgodna z RFC 3986.

  1. Niektóre znaki nie są zakodowane, ale powinny być. Te !()*znaki są wymienione w sekcji 2.2 RFC jako zarezerwowanego znaków, które muszą być jeszcze kodowanych NET zawodzi kodować te znaki.

  2. Niektóre znaki są zakodowane, ale nie powinny. Te .-_znaki nie są wymienione w sekcji 2.2 RFC jako zastrzeżonego znaku, który nie powinien zostać zakodowany jeszcze .NET błędnie koduje te znaki.

  3. RFC określa, że ​​aby zachować spójność, implementacje powinny używać HEXDIG pisanych wielkimi literami, gdzie .NET produkuje HEXDIG pisany małymi literami.

Charlie
źródło
4

Myślę, że ludzie tutaj zostali odsunięci na bok przez wiadomość UrlEncode. URLEncoding nie jest tym, czego chcesz - chcesz zakodować rzeczy, które nie będą działać jako nazwa pliku w systemie docelowym.

Zakładając, że chcesz trochę ogólności - nie krępuj się znaleźć nielegalnych znaków w kilku systemach (MacOS, Windows, Linux i Unix), połącz je, aby utworzyć zestaw znaków do ucieczki.

Jeśli chodzi o ucieczkę, HexEscape powinien być w porządku (Zastąpienie znaków% XX). Konwertuj każdy znak na bajty UTF-8 i koduj wszystko> 128, jeśli chcesz obsługiwać systemy, które nie obsługują Unicode. Ale są też inne sposoby, takie jak użycie ukośników odwrotnych „\” lub kodowania HTML „”. Możesz stworzyć swój własny. Wszystko, co każdy system musi zrobić, to „zakodować” niezgodny znak. Powyższe systemy pozwalają odtworzyć oryginalna nazwa - ale działa również coś takiego jak zastąpienie złych znaków znakiem spacjami.

W przypadku tej samej stycznej jak powyżej jedyny do użycia to

Uri.EscapeDataString

- Koduje wszystko, co jest potrzebne do OAuth, nie koduje rzeczy, których OAuth zabrania kodowania, i koduje przestrzeń jako% 20, a nie + (również w specyfikacji OATH) Patrz: RFC 3986. AFAIK, to jest najnowsza specyfikacja URI.

Gerard ONeill
źródło
3

Napisałem metodę C #, która url-koduje WSZYSTKIE symbole:

    /// <summary>
    /// !#$345Hf} → %21%23%24%33%34%35%48%66%7D
    /// </summary>
    public static string UrlEncodeExtended( string value )
    {
        char[] chars = value.ToCharArray();
        StringBuilder encodedValue = new StringBuilder();
        foreach (char c in chars)
        {
            encodedValue.Append( "%" + ( (int)c ).ToString( "X2" ) );
        }
        return encodedValue.ToString();
    }
Siergiej
źródło
1

Idealnie byłoby, gdyby poszedł w klasie o nazwie „FileNaming” lub może po prostu zmienić nazwę Encode na „FileNameEncode”. Uwaga: nie są one zaprojektowane do obsługi Pełnych ścieżek, tylko nazwy folderów i / lub plików. Najlepiej byłoby najpierw podzielić („/”) pełną ścieżkę, a następnie sprawdzić elementy. I oczywiście zamiast unii, możesz po prostu dodać znak „%” do listy znaków niedozwolonych w systemie Windows, ale myślę, że w ten sposób jest to bardziej pomocne / czytelne / oparte na faktach. Dekodowanie () jest dokładnie takie samo, ale przełącza opcję Zamień (Uri.HexEscape (s [0]), s) na „znak ucieczki” ze znakiem.

public static List<string> urlEncodedCharacters = new List<string>
{
  "/", "\\", "<", ">", ":", "\"", "|", "?", "%" //and others, but not *
};
//Since this is a superset of urlEncodedCharacters, we won't be able to only use UrlEncode() - instead we'll use HexEncode
public static List<string> specialCharactersNotAllowedInWindows = new List<string>
{
  "/", "\\", "<", ">", ":", "\"", "|", "?", "*" //windows dissallowed character set
};

    public static string Encode(string fileName)
    {
        //CheckForFullPath(fileName); // optional: make sure it's not a path?
        List<string> charactersToChange = new List<string>(specialCharactersNotAllowedInWindows);
        charactersToChange.AddRange(urlEncodedCharacters.
            Where(x => !urlEncodedCharacters.Union(specialCharactersNotAllowedInWindows).Contains(x)));   // add any non duplicates (%)

        charactersToChange.ForEach(s => fileName = fileName.Replace(s, Uri.HexEscape(s[0])));   // "?" => "%3f"

        return fileName;
    }

Dzięki @ simon-tewsi za bardzo przydatną tabelę powyżej!

m1m1k
źródło
przydatne również: Path.GetInvalidFileNameChars()
m1m1k
tak. Oto jeden ze sposobów, aby to zrobić: foreach (char c w System.IO.Path.GetInvalidFileNameChars ()) {nazwa_pliku = nazwa_pliku.Replace (c, '_'); }
netfed
0

Oprócz odpowiedzi @Dana Herberta, powinniśmy ogólnie zakodować tylko wartości.

Split ma parametr params Split ('&', '='); wyrażenie najpierw podzielone przez & następnie '=', więc elementy nieparzyste to wszystkie wartości do zakodowania pokazane poniżej.

public static void EncodeQueryString(ref string queryString)
{
    var array=queryString.Split('&','=');
    for (int i = 0; i < array.Length; i++) {
        string part=array[i];
        if(i%2==1)
        {               
            part=System.Web.HttpUtility.UrlEncode(array[i]);
            queryString=queryString.Replace(array[i],part);
        }
    }
}
Davut Gürbüz
źródło