web-dev-qa-db-fra.com

WebUtility.HtmlDecode contre HttpUtilty.HtmlDecode

J'utilisais WebUtilty.HtmlDecode pour décoder le HTML. Il s'avère qu'il ne décode pas correctement, par exemple, – est supposé décoder en un caractère "-", mais WebUtilty.HtmlDecode ne le décode pas. HttpUtilty.HtmlDecode, cependant, fait.

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


> –
> –

decode screenshot

La documentation pour les deux est la même: Convertit une chaîne encodée en HTML pour la transmission HTTP en une chaîne décodée.

Pourquoi sont-ils différents, lequel devrais-je utiliser et qu'est-ce qui changera si je passe à WebUtility.HtmlDecode pour que "-" soit décodé correctement?

22
zi3guw

La mise en œuvre des deux méthodes est en effet différente sur 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();
}

Fait intéressant, WebUtility n'existe pas sur WP7. En outre, l'implémentation de WebUtility dans WP8 est identique à celle de desktop. L'implémentation de HttpUtility.HtmlDecode sur le bureau est juste un wrapper autour de WebUtility.HtmlDecode. Enfin, Silverlight 5 a la même implémentation de HttpUtility.HtmlDecode que Windows Phone et n'implémente pas WebUtility.

À partir de là, je peux me permettre une hypothèse: puisque Windows Phone 7 est basé sur Silverlight, WP7 hérite de la version Silverlight de HttpUtility.HtmlDecode et WebUtility n’est pas présent. Puis vint WP8, dont le runtime est basé sur WinRT. WinRT a apporté WebUtility, et l'ancienne version de HttpUtility.HtmlDecode a été conservée pour assurer la compatibilité avec les anciennes applications WP7.

Pour savoir lequel vous devez utiliser ... Si vous souhaitez cibler WP7, vous n’avez pas d’autre choix que d’utiliser HttpUtility.HtmlDecode. Si vous ciblez WP8, choisissez simplement la méthode dont le comportement répond le mieux à vos besoins. WebUtility est probablement le choix à l'épreuve du temps, au cas où Microsoft déciderait d'abandonner le runtime Silverlight dans une prochaine version de Windows Phone. Mais je choisirais simplement le choix pratique de choisir HttpUtility pour ne pas avoir à vous soucier de soutenir manuellement l’exemple que vous avez donné dans votre question.

11
Kevin Gosse

Les méthodes font exactement la même chose . De plus, si vous essayez de les décompiler, les implémentations semblent être copiées d'une autre.

La différence est seulement usage prévu . HttpUtility est contenu dans l'assembly System.Web et devrait être utilisé dans les applications ASP.net construites sur cet assemblage. WebUtility est contenu dans l'assembly System référencé par presque toutes les applications et est fourni à des fins plus générales ou pour un usage client.

4
Jan Dobkowski

Juste pour informer les autres qui trouveront ceci dans la recherche. Utilisez n'importe quelle fonction mentionnée dans la question, mais n'utilisez jamais Windows.Data.Html.HtmlUtilities.ConvertToText(string input). Il est 70 fois plus lent que WebUtilty.HtmlDecode et produit des chutes! Crash sera nommé mshtml!IEPeekMessage dans le centre de développement. Il semble que cette fonction appelle InternetExplorer pour convertir la chaîne. Juste l'éviter.

2
crea7or