0

我正在尝试使用 Microsoft 图表控件生成自定义工具提示。Microsoft Chart Controls 支持使用关键字的功能,这有助于自动化您希望显示的数据。

例如,

string toolTip = string.Format("<div> {0}: {1} {3} ({2}) </div>", seriesName, "#VALY", "#VALX", "<br>");
series.MapAreaAttributes = "onfocus=\"if(this.blur)this.blur();\" onmouseover=\"DisplayTooltip('" + JavaScriptStringLiteral(toolTip) + "');\" onmouseout=\"DisplayTooltip('');\"";

在上面的代码中,“#VALY”和“#VALX”是关键字。在运行时,这些关键字将替换为实际值。在我的场景中,#VALY 是双精度,#VALX 是日期时间。

观察:

在此处输入图像描述

现在,如果我使用数据系列的工具提示属性,这将非常有效。不幸的是,Firefox 和Opera不(容易)支持多行工具提示。我试图通过使用自定义工具提示来非法使用此功能。

因此,我有 onmouseover 和 onmouseout 代码——这是负责工具提示的 JavaScript 代码。

问题是当 #VALX 被评估时,它包含非法的 JavaScript 字符。这会导致错误消息“Uncaught SyntaxError: Unexpected token ILLEGAL”

请注意,我已经使用 JavaScriptStringLiteral 方法包装了工具提示。这是效用函数:

private static readonly Regex scriptTagRegex = new Regex("script", RegexOptions.IgnoreCase | RegexOptions.Multiline);

    /// <summary>
    ///     Processes the provided string, creating a quoted JavaScript string literal.
    /// </summary>
    /// <param name="str">The string to process</param>
    /// <returns>A string containing a quoted JavaScript string literal</returns>
    public static string JavaScriptStringLiteral(string str)
    {
        var sb = new StringBuilder();
        sb.Append("\"");
        foreach (char c in str)
        {
            switch (c)
            {
                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("\"");

        // If a JavaScript tag contains "</script>", then it terminates a
        // script block.  Start by replacing each 's'/'S' with an escape
        // sequence so it doesn't trigger this.
        return scriptTagRegex.Replace(
            sb.ToString(),
            m => (m.Value[0] == 's' ? "\\u0073" : "\\u0053") + m.Value.Substring(1));
    }

如果 #VALX 没有在运行时进行评估,我相信这个实用方法可以解决我的问题。但是,因此,实用程序函数将“#VALX”评估为字符串文字。然后,在过滤掉任何非法字符后,评估#VALX 并将非法字符放入我的 JavaScript。

有没有办法防止这个问题?相当于 C# 中路径的“@”字符的东西?


我想出了解决方案,它很愚蠢

foreach (HistoricalDataValue value in data)
{
    series.Points.AddXY(string.Format("{0:d}{1}{0:T}", value.TimeStamp, "\\n"), value.AttributeValue);
}

请注意,这表示“\\n”。这曾经是说Environment.NewLine,但这不起作用。此外,如果您使用 Environment.NewLine -或- "\n",则由于运行时评估,您不能稍后编辑 "#VALX"。因此,您必须在添加 X 值时使用转义换行符,以便当 #VALX 获取它时,它已经正确格式化。

4

2 回答 2

1

使用AntiXss 库Microsoft.Security.Application.JavaScriptEncode(string input)中的函数。

于 2011-10-12T17:54:01.173 回答
1

当您调用时,JavaScriptStringLiteral您的代码已经打开了一个单引号字符串,而该函数返回一个已经用双引号括起来的字符串。

您应该从JavaScriptStringLiteral返回的内容中删除第一个和最后一个字符。

于 2011-10-12T18:06:10.220 回答