Invalid character breaking the script

829 views Asked by At

I am using this code to create a string of javascript code, and running them from C# code behind.

It is working fine for normal values, but breaking when ' (apostrophe) is there in the values.

StringBuilder sb = new StringBuilder();
sb.Append("<script>");

// Store transmission chrome feature.
for(int i=0; i < Transmission.Length; i++)
{
    sb.Append("var obj = {text: '" + Transmission[i][0] + "',"  
                                        + "value: '" + Transmission[i][1] +"'};");
    sb.Append("transChromeData.push(obj);");
}

sb.Append("</" + "script>");
this.RegisterStartupScript("Info", sb.ToString());
3

There are 3 answers

1
CodingIntrigue On

It will also break if someone adds a \ as the value. You need to escape characters which will break a Javascript string - the HttpUtility.JavaScriptStringEncode will do this for you:

StringBuilder sb = new StringBuilder();
sb.Append("<script>");

// Store transmission chrome feature.
for(int i=0; i < Transmission.Length; i++)
{
    sb.Append("var obj = {text: '" + HttpUtility.JavaScriptStringEncode(Transmission[i][0]) + "',"  
                                        + "value: '" + HttpUtility.JavaScriptStringEncode(Transmission[i][2]) +"'};");
    sb.Append("transChromeData.push(obj);");
}

sb.Append("</" + "script>");
this.RegisterStartupScript("Info", sb.ToString());

For archaic versions of .NET, you'll need to roll your own. Rick Strahl has a good implementation which covers different JS characters:

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 '\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();
}
0
Emanuele On

use Microsoft JScript escaping function

Microsoft.JScript.GlobalObject.escape("String to escape");

below your code edited

StringBuilder sb = new StringBuilder();
sb.Append("<script>");

// Store transmission chrome feature.
for(int i=0; i < Transmission.Length; i++)
{
    sb.Append("var obj = {text: '" + Microsoft.JScript.GlobalObject.escape(Transmission[i][0]) + "',"  
                                        + "value: '" + Microsoft.JScript.GlobalObject.escape(Transmission[i][1]) +"'};");
    sb.Append("transChromeData.push(obj);");
}

sb.Append("</" + "script>");
this.RegisterStartupScript("Info", sb.ToString());

alternatively you can use

HttpUtility.UrlDecode

but it will be unsafe

on asp.net 1.1 try to use the code suggested here http://www.west-wind.com/weblog/posts/2007/Jul/14/Embedding-JavaScript-Strings-from-an-ASPNET-Page

0
Alessandro D'Andria On

Try this:

StringBuilder sb = new StringBuilder();
sb.Append("<script>");

// Store transmission chrome feature.
for (int i = 0; i < Transmission.Length; i++)
{
    sb.Append("var obj = {text: '")
        .Append(Escape(Transmission[i][0]))
        .Append("',")
        .Append("value: '")
        .Append(Escape(Transmission[i][1]))
        .Append("'};")
        .Append("transChromeData.push(obj);");
}

sb.Append("</script>");
this.RegisterStartupScript("Info", sb.ToString());

...

static string Escape(string source)
{
    return source.Replace(@"'",  @"\'");
}