HttpUtility.HtmlEncode不编码所有内容

时间:2009-02-13 20:53:59

标签: c# html encoding utf-8

我正在使用C#和.Net 3.5中的桌面客户端程序与Web服务器进行交互。我正在使用Fiddler查看Web浏览器发送的流量,并模拟它。可悲的是,这台服务器已经很老了,对于charsets和utf-8的概念有点困惑。大多数情况下它使用Latin-1。

当我在包含“特殊”字符的Web浏览器中输入数据时,例如“Ωπℵ∞♣♥ ♈♉♊♋♌♍♏♐♑♓♓“fiddler告诉我他们从浏览器传送到服务器如下:"♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓ "

但是对于我的客户端,HttpUtility.HtmlEncode不会转换这些字符,而是将它们保留为原样。我需要调用什么来将“♈”转换为♈等等?

7 个答案:

答案 0 :(得分:13)

HtmlEncode的返回值类型是一个字符串,它是Unicode的,因此不需要对这些字符进行编码。

如果输出流的编码与这些字符不兼容,请使用如下的HtmlEncode: -

 HttpUtility.HtmlEncode(outgoingString, Response.Output);

HtmlEncode然后适当地转义字符。

答案 1 :(得分:12)

Rich Strahl刚刚发布了一篇博客文章Html and Uri String Encoding without System.Web,其中有一些自定义代码可以编码较高范围的字符。

/// <summary>
/// HTML-encodes a string and returns the encoded string.
/// </summary>
/// <param name="text">The text string to encode. </param>
/// <returns>The HTML-encoded text.</returns>
public static string HtmlEncode(string text)
{
    if (text == null)
        return null;

    StringBuilder sb = new StringBuilder(text.Length);

    int len = text.Length;
    for (int i = 0; i < len; i++)
    {
        switch (text[i])
        {

            case '<':
                sb.Append("&lt;");
                break;
            case '>':
                sb.Append("&gt;");
                break;
            case '"':
                sb.Append("&quot;");
                break;
            case '&':
                sb.Append("&amp;");
                break;
            default:
                if (text[i] > 159)
                {
                    // decimal numeric entity
                    sb.Append("&#");
                    sb.Append(((int)text[i]).ToString(CultureInfo.InvariantCulture));
                    sb.Append(";");
                }
                else
                    sb.Append(text[i]);
                break;
        }
    }
    return sb.ToString();
}

答案 2 :(得分:11)

看起来非常低效,但我能想到的唯一方法是浏览每个角色:

public static string MyHtmlEncode(string value)
{
   // call the normal HtmlEncode first
   char[] chars = HttpUtility.HtmlEncode(value).ToCharArray();
   StringBuilder encodedValue = new StringBuilder();
   foreach(char c in chars)
   {
      if ((int)c > 127) // above normal ASCII
         encodedValue.Append("&#" + (int)c + ";");
      else
         encodedValue.Append(c);
   }
   return encodedValue.ToString();
}

答案 3 :(得分:3)

Microsoft的AntiXSS库正确编码了这些字符。

AntiXSS on Codeplex

Nuget package(添加作为参考的最佳方式)

答案 4 :(得分:2)

似乎HtmlEncode仅用于编码放入HTML文档的字符串,其中只有/&lt; &GT; &安培;等引起问题。对于URL,只需将HtmlEncode替换为UrlEncode。

答案 5 :(得分:1)

上面的@bdukes响应将完成这项工作,但如果我们假设大多数字符在此范围内,我们可以更快。注意引用的'Â'(unicode 0x0100)

/// <summary>.Net 2.0's HttpUtility.HtmlEncode will not properly encode
/// Unicode characters above 0xFF.  This may be fixed in newer 
/// versions.</summary>
public static string HtmlEncode(string s)
{
    // Let .Net 2.0 get right what it gets right.
    s = HttpUtility.HtmlEncode(s);

    // Search for first non-ASCII.  Hopefully none and we can just 
    // return s.
    int num = IndexOfHighChar(s, 0);
    if (num == -1)
        return s;
    int old_num = 0;
    StringBuilder sb = new StringBuilder();
    do {
        sb.Append(s, old_num, num - old_num);
        sb.Append("&#");
        sb.Append(((int)s[num]).ToString(NumberFormatInfo.InvariantInfo));
        sb.Append(';');
        old_num = num + 1;
        num = IndexOfHighChar(s, old_num);
    } while (num != -1);
    sb.Append(s, old_num, s.Length - old_num);
    return sb.ToString();
}

static unsafe int IndexOfHighChar(string s, int start)
{
    int num = s.Length - start;
    fixed (char* str = s) {
        char* chPtr = str + start;
        while (num > 0) {
            char ch = chPtr[0];
            if (ch >= 'Ā')
                return s.Length - num;
            chPtr++;
            num--;
        }
    }
    return -1;
}

答案 6 :(得分:0)

您可以随时更换不需要的ASCII,如下所示:当没有if语句编码时,结果字符串为&#34;这意味着我在哭:&#39;&amp;&#39;#39;)对于无论什么原因&#39;特殊字符&#39;处理并替换为HTML char。

string text = "This means I am crying :'(";

string encoded = HttpUtility.HtmlEncode(text);
if(encoded.Contains("&#39;"))
{
    encoded = encoded.Replace("&#39;", "'");
}