it-swarm.com.de

WebUtility.HtmlDecode vs. HttpUtilty.HtmlDecode

Ich habe WebUtilty.HtmlDecode verwendet, um HTML zu decodieren. Es stellt sich heraus, dass es nicht richtig decodiert. Beispielsweise soll – zu einem "-" Zeichen decodiert werden, aber WebUtilty.HtmlDecode decodiert es nicht. HttpUtilty.HtmlDecode tut dies jedoch.

Debug.WriteLine(WebUtility.HtmlDecode("–"));
Debug.WriteLine(HttpUtility.HtmlDecode("–"));


> –
> –

decode screenshot

Die Dokumentation für beide ist die gleiche: Konvertiert eine Zeichenfolge, die für die HTTP-Übertragung HTML-kodiert wurde, in eine dekodierte Zeichenfolge.

Warum unterscheiden sie sich, welche sollte ich verwenden, und was wird sich ändern, wenn ich zu WebUtility.HtmlDecode wechsle, um "-" korrekt decodieren zu lassen?

22
zi3guw

Die Implementierung der beiden Methoden unterscheidet sich in der Tat unter Windows Phone.

WebUtility.HtmlDecode:

public static void HtmlDecode(string value, TextWriter output)
{
    if (value != null)
    {
        if (output == null)
        {
            throw new ArgumentNullException("output");
        }
        if (!StringRequiresHtmlDecoding(value))
        {
            output.Write(value);
        }
        else
        {
            int length = value.Length;
            for (int i = 0; i < length; i++)
            {
                bool flag;
                uint num4;
                char ch = value[i];
                if (ch != '&')
                {
                    goto Label_01B6;
                }
                int num3 = value.IndexOfAny(_htmlEntityEndingChars, i + 1);
                if ((num3 <= 0) || (value[num3] != ';'))
                {
                    goto Label_01B6;
                }
                string entity = value.Substring(i + 1, (num3 - i) - 1);
                if ((entity.Length <= 1) || (entity[0] != '#'))
                {
                    goto Label_0188;
                }
                if ((entity[1] == 'x') || (entity[1] == 'X'))
                {
                    flag = uint.TryParse(entity.Substring(2), NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out num4);
                }
                else
                {
                    flag = uint.TryParse(entity.Substring(1), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out num4);
                }
                if (flag)
                {
                    switch (_htmlDecodeConformance)
                    {
                        case UnicodeDecodingConformance.Strict:
                            flag = (num4 < 0xd800) || ((0xdfff < num4) && (num4 <= 0x10ffff));
                            goto Label_0151;

                        case UnicodeDecodingConformance.Compat:
                            flag = (0 < num4) && (num4 <= 0xffff);
                            goto Label_0151;

                        case UnicodeDecodingConformance.Loose:
                            flag = num4 <= 0x10ffff;
                            goto Label_0151;
                    }
                    flag = false;
                }
            Label_0151:
                if (!flag)
                {
                    goto Label_01B6;
                }
                if (num4 <= 0xffff)
                {
                    output.Write((char) num4);
                }
                else
                {
                    char ch2;
                    char ch3;
                    ConvertSmpToUtf16(num4, out ch2, out ch3);
                    output.Write(ch2);
                    output.Write(ch3);
                }
                i = num3;
                goto Label_01BD;
            Label_0188:
                i = num3;
                char ch4 = HtmlEntities.Lookup(entity);
                if (ch4 != '\0')
                {
                    ch = ch4;
                }
                else
                {
                    output.Write('&');
                    output.Write(entity);
                    output.Write(';');
                    goto Label_01BD;
                }
            Label_01B6:
                output.Write(ch);
            Label_01BD:;
            }
        }
    }
}

HttpUtility.HtmlDecode:

public static string HtmlDecode(string html)
{
    if (html == null)
    {
        return null;
    }
    if (html.IndexOf('&') < 0)
    {
        return html;
    }
    StringBuilder sb = new StringBuilder();
    StringWriter writer = new StringWriter(sb, CultureInfo.InvariantCulture);
    int length = html.Length;
    for (int i = 0; i < length; i++)
    {
        char ch = html[i];
        if (ch == '&')
        {
            int num3 = html.IndexOfAny(s_entityEndingChars, i + 1);
            if ((num3 > 0) && (html[num3] == ';'))
            {
                string entity = html.Substring(i + 1, (num3 - i) - 1);
                if ((entity.Length > 1) && (entity[0] == '#'))
                {
                    try
                    {
                        if ((entity[1] == 'x') || (entity[1] == 'X'))
                        {
                            ch = (char) int.Parse(entity.Substring(2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);
                        }
                        else
                        {
                            ch = (char) int.Parse(entity.Substring(1), CultureInfo.InvariantCulture);
                        }
                        i = num3;
                    }
                    catch (FormatException)
                    {
                        i++;
                    }
                    catch (ArgumentException)
                    {
                        i++;
                    }
                }
                else
                {
                    i = num3;
                    char ch2 = HtmlEntities.Lookup(entity);
                    if (ch2 != '\0')
                    {
                        ch = ch2;
                    }
                    else
                    {
                        writer.Write('&');
                        writer.Write(entity);
                        writer.Write(';');
                        continue;
                    }
                }
            }
        }
        writer.Write(ch);
    }
    return sb.ToString();
}

Interessanterweise existiert WebUtility nicht in WP7. Auch die WP8-Implementierung von WebUtility ist identisch mit der Desktop-Implementierung. Die Desktop-Implementierung von HttpUtility.HtmlDecode ist nur ein Wrapper um WebUtility.HtmlDecode. Nicht zuletzt hat Silverlight 5 die gleiche Implementierung von HttpUtility.HtmlDecode wie Windows Phone und implementiert WebUtility nicht.

Von dort aus kann ich eine Vermutung wagen: Da die Windows Phone 7-Laufzeit auf Silverlight basiert, wurde WP7 von der Silverlight-Version von HttpUtility.HtmlDecode übernommen und WebUtility war nicht vorhanden. Dann kam WP8, dessen Laufzeit auf WinRT basiert. WinRT brachte WebUtility mit, und die alte Version von HttpUtility.HtmlDecode wurde beibehalten, um die Kompatibilität mit den älteren WP7-Apps sicherzustellen.

Um herauszufinden, welches Sie verwenden sollten ... Wenn Sie WP7 als Ziel verwenden möchten, haben Sie keine andere Wahl, als HttpUtility.HtmlDecode zu verwenden. Wenn Sie auf WP8 abzielen, wählen Sie einfach die Methode aus, deren Verhalten Ihren Anforderungen am besten entspricht. WebUtility ist wahrscheinlich die zukunftssichere Wahl, nur für den Fall, dass Microsoft die Silverlight-Laufzeit in einer zukünftigen Version von Windows Phone aufgibt. Aber ich würde mich einfach für die praktische Entscheidung entscheiden, HttpUtility zu wählen, um sich nicht darum kümmern zu müssen, das von Ihnen in Ihre Frage gestellte Beispiel manuell zu unterstützen.

11
Kevin Gosse

Die Methoden machen genau dasselbe . Wenn Sie versuchen, sie zu dekompilieren, sehen die Implementierungen so aus, als wäre eine Version von einer anderen kopiert worden.

Der Unterschied ist nur Verwendungszweck . HttpUtility ist in der System.Web Assembly enthalten und wird voraussichtlich in ASP.net-Anwendungen verwendet, die über dieser Assembly erstellt werden. WebUtility ist in der System-Assembly enthalten, auf die in fast allen Anwendungen verwiesen wird, und wird für allgemeinere Zwecke oder zur Verwendung durch Kunden bereitgestellt.

4
Jan Dobkowski

Nur um andere zu benachrichtigen, die dies auf der Suche finden werden. Verwenden Sie eine Funktion, die in der Frage erwähnt wurde, verwenden Sie jedoch niemals Windows.Data.Html.HtmlUtilities.ConvertToText(string input). Es ist 70 Mal langsamer als WebUtilty.HtmlDecode und führt zu Abstürzen! Der Absturz wird im DevCenter als mshtml!IEPeekMessage bezeichnet. Es sieht so aus, als würde diese Funktion InternetExplorer aufrufen, um die Zeichenfolge zu konvertieren. Vermeide es einfach.

2
crea7or