是否存在将.NET字符串编码为JavaScript字符串以用于MS Ajax的标准方法?


73

我正在尝试使用RegisterStartUpScript.NET 3.5中MS ScriptManager的方法将SQL Server异常的输出传递给客户端。对于某些错误,这可以正常工作,但是当异常包含单引号时,警报将失败。

我不想只转义单引号。我是否可以调用一个标准函数来转义用于JavaScript的任何特殊字符?

string scriptstring = "alert('" + ex.Message + "');";         
ScriptManager.RegisterStartupScript(this, this.GetType(), "Alert", scriptstring , true);

编辑

感谢@tpeczek,代码 几乎对我:),但稍作修改(转义单引号),就可以了。

我在这里包括了我的修订版本...

public class JSEncode
{
    /// <summary>
    /// Encodes a string to be represented as a string literal. The format
    /// is essentially a JSON string.
    /// 
    /// The string returned includes outer quotes 
    /// Example Output: "Hello \"Rick\"!\r\nRock on"
    /// </summary>
    /// <param name="s"></param>
    /// <returns></returns>
    public static string EncodeJsString(string s)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("\"");
        foreach (char c in s)
        {
            switch (c)
            {
                case '\'':
                    sb.Append("\\\'");
                    break;
                case '\"':
                    sb.Append("\\\"");
                    break;
                case '\\':
                    sb.Append("\\\\");
                    break;
                case '\b':
                    sb.Append("\\b");
                    break;
                case '\f':
                    sb.Append("\\f");
                    break;
                case '\n':
                    sb.Append("\\n");
                    break;
                case '\r':
                    sb.Append("\\r");
                    break;
                case '\t':
                    sb.Append("\\t");
                    break;
                default:
                    int i = (int)c;
                    if (i < 32 || i > 127)
                    {
                        sb.AppendFormat("\\u{0:X04}", i);
                    }
                    else
                    {
                        sb.Append(c);
                    }
                    break;
            }
        }
        sb.Append("\"");

        return sb.ToString();
    }
}

如下所述-原始来源:这里

Answers:


184

9
因其出色的答案而被投票-尽管只能在.NET 4中使用
Rich Andrews 2010年

5
我认为,当有一个针对特定任务的框架功能(如这样)时,它通常比自己动手更可靠,更准确,因此最好坚持下去
。。–路加福音

本文展示了如何在.NET 4之前
rdans

2
@eddy,问题指出.NET 3.5,而不是4,并且此代码仅适用于4+。这就是为什么它不是答案。
Rich Andrews 2014年

1
注意:对于那些寻求将国际字符编码为转义序列的方法的人,这将不起作用。有关此问题的解决方案,请参见此问题。
R. Salisbury

10

带有此功能的一个探针是,它不会对封装HTML时通常带外的字符进行编码...因此,如果尝试"在属性值中包含字符串,或者具有序列的字符串</script>在脚本元素内具有。这可能导致脚本注入和XSS。

您可以添加:

            case '<':
                sb.Append("\\x3C");
                break;
            case '"':
                sb.Append("\\x22");
                break;
            case '&':
                sb.Append("\\x26");
                break;

通常,使用标准JSON编码器可能比酿造自己的JS字符串文字编码器更好。这将允许您将任何简单的数据类型传递给JS,而不仅仅是字符串。

在.NET 3.5你JavaScriptSerializer,但是请注意,虽然这确实编码<,以\u003C(使输出将适用于使用<script>元素),它没有做编码&",所以HTML转义将需要包括的内容等XHTML脚本元素将需要属性值和CDATA包装器。

(与许多JSON编码器相同,它也无法对U + 2028 LINE SEPARATOR和U + 2029 PARAGRAPH SEPARATOR字符进行编码。由于对所有非A​​SCII字符进行转义,因此上面的代码可以实现。这些字符包含在JS字符串文字中,因为JavaScript会无助地将它们与ASCII换行符一样。)


1
伟大的写作。请注意,JavaScriptSerializer通过ASP.NET AJAX 1.0带外发行版(microsoft.com/downloads/en/…)在.NET 2中也可以使用。
bdukes

1
在那种情况下,您不会使用HttpUtility.HtmlAttributeEncode(HttpUtility.JavaScriptStringEncode(unencodedString))还是HttpUtility.HtmlEncode(HttpUtility.JavaScriptStringEncode(unencodedString))取决于上下文?
马丁·布朗

@MartinBrown:可以使用其中任何一种注入JS-in-HTML属性,是的(尽管这样做通常是一个坏主意)。该HtmlEncodeHtmlAttributeEncode方法命名好奇; 似乎应该为属性值更好地工作,而应该为文本内容更好地工作,但是根据参考资料判断,在实践中并没有这种区别。它们只是两个任意不同实现的HTML编码器。
bobince

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.