Escape Quote in C # para el consumo de JavaScript

Tengo un controlador web ASP.Net que devuelve resultados de una consulta en formato JSON

public static String dt2JSON(DataTable dt) { String s = "{\"rows\":["; if (dt.Rows.Count > 0) { foreach (DataRow dr in dt.Rows) { s += "{"; for (int i = 0; i < dr.Table.Columns.Count; i++) { s += "\"" + dr.Table.Columns[i].ToString() + "\":\"" + dr[i].ToString() + "\","; } s = s.Remove(s.Length - 1, 1); s += "},"; } s = s.Remove(s.Length - 1, 1); } s += "]}"; return s; } 

El problema es que a veces los datos devueltos tienen comillas y necesito javascript-escapar de estos para que puedan crearse correctamente en un objeto js. Necesito una forma de encontrar citas en mis datos (las citas no están disponibles todas las veces) y colocar un carácter “/” delante de ellos.

Ejemplo de texto de respuesta (incorrecto):

 {"rows":[{"id":"ABC123","length":"5""}, {"id":"DEF456","length":"1.35""}, {"id":"HIJ789","length":"36.25""}]} 

Necesitaría escapar del “entonces mi respuesta debería ser:

 {"rows":[{"id":"ABC123","length":"5\""}, {"id":"DEF456","length":"1.35\""}, {"id":"HIJ789","length":"36.25\""}]} 

Además, soy bastante nuevo en C # (en general, la encoding en general) así que si algo más en mi código parece tonto, házmelo saber.

Para .net 4.0 + existe el estándar HttpUtility.JavaScriptStringEncode

Para la solución de viento oeste anterior descrita por Lone Coder es bastante agradable

Aquí hay un método eficiente y robusto que encontré en http://www.west-wind.com/weblog/posts/114530.aspx

 ///  /// 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" ///  ///  ///  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(); } 

Creo que deberías mirar la clase JavaScriptSerializer. Es mucho más estable y manejará correctamente cualquier tipo de datos o caracteres de escape, etc. Además, su código se verá mucho más limpio.

En tu caso, tu clase puede verse así:

 public static String dt2JSON(DataTable dt) { var rows = new List(); foreach(DataRow row in dt.Rows) { var rowData = new Dictionary(); foreach(DataColumn col in dt.Columns) rowData[col.ColumnName] = row[col]; rows.Add(rowData); } var js = new JavaScriptSerializer(); return js.Serialize(new { rows = rows }); } 

Este método devolverá una cadena json serializada correctamente … Por ejemplo, algo como esto:

 {"rows":[{"id":1,"name":"hello"},{"id":2,"name":"bye"}]} 

¡Que te diviertas! 🙂

Para escapar correctamente de un literal de cadena para Javascript, primero escapa de todos los caracteres de barra invertida, luego se escapa de las comillas (o apóstrofes si los usa como delimitadores de cadena).

Entonces, lo que necesitas es:

 value.Replace("\\","\\\\").Replace("\"","\\\"") 

Lo que más salta a la vista es que está utilizando la concatenación de cadenas en un bucle. Esto es malo, ya que se escala muy pobremente. El operador + = no agrega caracteres al final de la cadena existente (ya que las cadenas son inmutables y nunca se pueden cambiar), en su lugar copia la cadena y los caracteres agregados a una nueva cadena. A medida que copie más y más datos cada vez, cada fila adicional duplica aproximadamente el tiempo de ejecución del método. Use un StringBuilder para construir la cadena en su lugar.

Use la propiedad ColumnName para obtener el nombre de una columna en lugar del método ToString . El método ToString devuelve el valor de la propiedad Expression si está configurado, solo si no se establece devuelve la propiedad ColumnName .

 public static String dt2JSON(DataTable dt) { StringBuilder s = new StringBuilder("{\"rows\":["); bool firstLine = true; foreach (DataRow dr in dt.Rows) { if (firstLine) { firstLine = false; } else { s.Append(','); } s.Append('{'); for (int i = 0; i < dr.Table.Columns.Count; i++) { if (i > 0) { s.Append(','); } string name = dt.Columns[i].ColumnName; string value = dr[i].ToString(); s.Append('"') .Append(name.Replace("\\","\\\\").Replace("\"","\\\"")) .Append("\":\"") .Append(value.Replace("\\","\\\\").Replace("\"","\\\"")) .Append('"'); } s.Append("}"); } s.Append("]}"); return s.ToString(); } 
 string.Replace(, @"\"", @"\\""); 

¿Por qué no haces esto?

 string correctResponseText = wrongResponseText.Replace("\"", "\\\""); 

Funciona cuando necesito enviar cadenas desde la etiqueta C # a html.

  HttpUtility.HtmlEncode 

Bueno, para empezar, no necesitas cotizaciones para las llaves.

 {rows:[,]} is valid. and you could dt.Table.Columns[i].ToString().Replace("\","") 

Pero si desea conservar las comillas dobles, las comillas simples funcionan de la misma manera que las comillas dobles en JS

De lo contrario, podrías hacer

 String.Format("{name: \"{0}\"}",Columns[i].ToString().Replace("\",""))