2010-05-27 3 views
68

J'essaie de transmettre la sortie d'une exception SQL Server au client en utilisant la méthode RegisterStartUpScript de MS ScriptManager dans .NET 3.5. Cela fonctionne correctement pour certaines erreurs, mais lorsque l'exception contient des guillemets simples, l'alerte échoue.Existe-t-il un moyen standard de coder une chaîne .NET en chaîne JavaScript pour une utilisation dans MS Ajax?

Je ne veux pas seulement échapper seulement des guillemets simples. Y at-il une fonction standard que je peux appeler pour échapper des caractères spéciaux pour une utilisation en JavaScript?

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

EDIT:

Merci @tpeczek, le code presque a fonctionné pour moi :) mais avec une légère modification (l'échappement des guillemets simples), il fonctionne un régal.

J'ai inclus ma version modifiée ici ...

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

Comme mentionné ci-dessous - source d'origine: here

Répondre

9

A probem avec cette fonction est qu'elle ne code pas les caractères qui sont généralement out-of-band dans l'encapsulation HTML ... donc vous auriez des problèmes si vous essayiez d'inclure une chaîne avec " dans une valeur d'attribut, ou si vous aviez une chaîne avec la séquence </script> dans un élément de script. Cela pourrait conduire à l'injection de script et XSS.

Vous pouvez ajouter:

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

En général, il serait sans doute préférable d'utiliser un codeur standard JSON que brasser votre propre chaîne JS encodeur littéral. Cela vous permettra de passer n'importe quel type de données simple à JS plutôt que seulement des chaînes.

Dans .NET 3.5, vous obtenez JavaScriptSerializer, notez toutefois que, si ce -t encode < à \u003C (de sorte que la sortie sera adapté à une utilisation dans un élément <script>), il ne encode & ou ", donc l'échappement HTML serait nécessaire pour inclure un tel contenu dans une valeur d'attribut et un wrapper CDATA serait nécessaire pour les éléments de script XHTML.

(Comme de nombreux codeurs JSON, il ne parvient pas à encoder les caractères U + 2028 LINE SEPARATOR et U + 2029 PARAGRAPH SEPARATOR car le code ci-dessus échappe à tous les caractères non-ASCII. littéral 'erreurs lorsque ces caractères sont inclus dans un littéral de chaîne JS, car JavaScript les traite de la même manière qu'un saut de ligne ASCII.)

+1

Grand article. Notez que 'JavaScriptSerializer' est également disponible dans .NET 2 via la version hors bande d'ASP.NET AJAX 1.0 (http://www.microsoft.com/downloads/fr/details.aspx?FamilyID=ca9d90fa-e8c9- 42e3-aa19-08e2c027f5d6 & displaylang = fr). – bdukes

+0

Dans ce cas, n'utilisez-vous pas 'HttpUtility.HtmlAttributeEncode (HttpUtility.JavaScriptStringEncode (unencodedString))' ou 'HttpUtility.HtmlEncode (HttpUtility.JavaScriptStringEncode (unencodedString))' en fonction du contexte? –

+0

@MartinBrown: vous pouvez utiliser l'un ou l'autre pour injecter dans l'attribut JS-in-HTML, oui (bien que ce soit généralement une mauvaise idée de le faire). Les méthodes 'HtmlEncode' et' HtmlAttributeEncode' sont curieusement nommées; il semble que l'on doive mieux travailler pour les valeurs d'attribut et on devrait mieux travailler pour le contenu textuel, mais il n'y a pas de distinction dans la pratique à en juger par la source de référence. Ce ne sont que deux encodeurs HTML arbitrairement mis en œuvre différemment. – bobince

163

Avez-vous jeté un coup d'œil à HttpUtility.JavaScriptStringEncode?

+9

Upvoted parce que c'est une bonne réponse - ne fonctionne que dans .NET 4 si –

+5

Je pense que quand il y a une fonction de cadre pour une tâche spécifique (comme ceci), il est souvent plus fiable et précis que les do-it-yourself, Il vaut mieux s'en tenir à ça. – Luke

+0

Y a-t-il une solution de contournement comme celle de 3.5? –

Questions connexes