web-dev-qa-db-fra.com

Attributs HTML conditionnels utilisant Razor MVC3

La variable strCSSClass a souvent une valeur mais est parfois vide.

Je ne souhaite pas inclure un class = "" vide dans le code HTML de cet élément d'entrée, ce qui signifie que si strCSSClass est vide, je ne veux pas du tout l'attribut class =.

Voici un moyen de créer un attribut HTML conditionnel:

<input type="text" id="@strElementID" @(CSSClass.IsEmpty() ? "" : "class=" + strCSSClass) />

Y a-t-il une manière plus élégante de faire ceci? Plus précisément, je pourrais suivre la même syntaxe que celle utilisée dans les autres parties de l'élément: class = "@ strCSSClass"?

96
tony722

Vous ne l'avez pas entendu de ma part, le PM pour Razor, mais dans Razor 2 (Web Pages 2 et MVC 4), nous aurons des attributs conditionnels intégrés à Razor (à partir de MVC 4 RC testé avec succès), vous pouvez donc dire des choses comme ça ...

<input type="text" id="@strElementID" class="@strCSSClass" />

Si strCSSClass est null, l'attribut de classe ne sera pas rendu du tout.

SSSHHH ... ne le dis pas. :)

155
Erik Porter

Notez que vous pouvez faire quelque chose comme ceci (au moins dans MVC3):

<td align="left" @(isOddRow ? "class=TopBorder" : "style=border:0px") >

Ce que je croyais être le rasoir ajoutant des guillemets était en fait le navigateur. Comme Rism l'a souligné lors des tests avec MVC 4 (je n'ai pas testé avec MVC 3 mais je suppose que le comportement n'a pas changé), cela produit en réalité class=TopBorder, Mais les navigateurs peuvent analyser cette amende. Les analyseurs HTML pardonnent quelque peu les citations d'attributs manquantes, mais cela peut casser si vous avez des espaces ou certains caractères.

<td align="left" class="TopBorder" >

OR

<td align="left" style="border:0px" >

Qu'est-ce qui ne va pas avec vos propres citations?

Si vous essayez d'utiliser certaines des conventions C # habituelles pour les citations imbriquées, vous vous retrouverez avec plus de citations que prévu, car Razor tente de leur échapper en toute sécurité. Par exemple:

<button type="button" @(true ? "style=\"border:0px\"" : string.Empty)>

Ceci devrait être évalué à <button type="button" style="border:0px"> Mais Razor échappe toute la sortie de C # et produit donc:

style=&quot;border:0px&quot;

Vous ne verrez ceci que si vous visualisez la réponse sur le réseau. Si vous utilisez un inspecteur HTML, vous voyez souvent le DOM, pas le HTML brut. Les navigateurs analysent le code HTML dans le DOM, et certaines subtilités sont déjà appliquées à la représentation DOM après analyse. Dans ce cas, le navigateur voit qu'il n'y a pas de guillemets autour de la valeur d'attribut, les ajoute:

style="&quot;border:0px&quot;"

Mais dans l'inspecteur DOM, les codes de caractères HTML s'affichent correctement pour que vous puissiez voir:

style=""border:0px""

Dans Chrome, si vous cliquez avec le bouton droit de la souris et sélectionnez Modifier le code HTML, il revient en arrière afin que vous puissiez voir ces codes de caractères HTML désagréables, ce qui indique clairement que vous avez de véritables guillemets extérieurs et des guillemets intérieurs codés au format HTML.

Donc, le problème en essayant de vous citer vous-même est que Razor leur échappe.

Si vous voulez un contrôle complet des devis

Utilisez Html.Raw pour empêcher les devis d’échapper:

<td @Html.Raw( someBoolean ? "rel='tooltip' data-container='.drillDown a'" : "" )>

Rendus comme:

<td rel='tooltip' title='Drilldown' data-container='.drillDown a'>

Ce qui précède est parfaitement sûr car je ne produis aucun code HTML à partir d’une variable. La seule variable impliquée est la condition ternaire. Cependant, attention que cette dernière technique peut vous exposer à certains problèmes de sécurité si vous créez des chaînes à partir de données fournies par l'utilisateur. Par exemple. si vous avez créé un attribut à partir de champs de données provenant de données fournies par l'utilisateur, l'utilisation de Html.Raw signifie que la chaîne pourrait contenir une fin prématurée de l'attribut et de la balise, puis commencez une balise de script exécutant une action au nom de l'utilisateur actuellement connecté. (éventuellement différent de l'utilisateur connecté). Peut-être avez-vous une page avec une liste de toutes les images des utilisateurs et définissez-vous une info-bulle avec le nom d'utilisateur de chaque personne, et un utilisateur se nommera lui-même '/><script>$.post('changepassword.php?password=123')</script> et maintenant tout autre utilisateur visualisant cette page aura son mot de passe instantanément changé en un mot de passe que l'utilisateur malveillant connaît.

118
AaronLS

Je suppose qu'un moyen un peu plus pratique et structuré consiste à utiliser HTML helper. À votre avis, cela peut ressembler à:

@{
 var htmlAttr = new Dictionary<string, object>();
 htmlAttr.Add("id", strElementId);
 if (!CSSClass.IsEmpty())
 {
   htmlAttr.Add("class", strCSSClass);
 }
}

@* ... *@

@Html.TextBox("somename", "", htmlAttr)

Si cela vous est utile, je vous recommande de définir le dictionnaire htmlAttr dans votre modèle afin que votre vue ne nécessite pas de @{ } blocs logiques (soyez plus clair).

11
Yaschur