0

Microsoft Chart Controls を使用してカスタム ツールチップを生成しようとしています。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 は double で、#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

コードを呼び出すと、JavaScriptStringLiteralすでに一重引用符で囲まれた文字列が開かれていますが、その関数はすでに二重引用符で囲まれた文字列を返します。

返される文字から最初と最後の文字を削除する必要がありJavaScriptStringLiteralます。

于 2011-10-12T18:06:10.220 に答える
1

AntiXss ライブラリMicrosoft.Security.Application.JavaScriptEncode(string input)の関数を使用します。

于 2011-10-12T17:54:01.173 に答える