Razor MVC3を使用した条件付きHTML属性


100

変数strCSSClassには値が含まれることがよくありますが、空の場合もあります。

この入力要素のHTMLに空のclass = ""を含めたくありません。つまり、strCSSClassが空の場合、class =属性はまったく必要ありません。

以下は、条件付きHTML属性を実行する1つの方法です。

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

これを行うよりエレガントな方法はありますか?具体的には、要素の他の部分で使用されているものと同じ構文に従うことができる1つ:class = "@ strCSSClass"?

回答:


160

私、RazorのPMからは聞いていませんでしたが、Razor 2(Webページ2およびMVC 4)では、Razorに条件付き属性が組み込まれているため(MVC 4 RCのテストは正常にテストされています)、次のように言うことができます。このようなもの...

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

strCSSClassがnullの場合、クラス属性はまったくレンダリングされません。

SSSHHH ...わからない。:)


1
うん、あなたは間違いなく私のものを答えとして受け入れるべきではありません。とは言っても、今日それを行うためのより明確な方法はありません(したがって、より明確な方法を作成しています)。おそらくそれを行うための最もクリーンな方法はHtml.TextBoxを使用することですが、それにはあまり望ましくないものの異なるセットがあります。:(私たちが追加しているものを気に入ってくれてうれしいです。:)
Erik Porter

1
しかし、どうすればRazor属性を他のテキストと組み合わせることができますか?以下を作成する必要があります:... id = "track_@track.ID"。... id = "track_2"のようなものが期待されていましたが、次の出力が生成されました:... id = "track_@track.ID" ...
Laserson

2
Razorを括弧で囲んでコードを評価するように強制できます。id = "track _ @(track.ID)"
エリックポーター、

1
これがMVC 4で正常に機能することを示すメモを追加しました。MVC3を使用している場合は、以下の私の回答を参照してください。
AaronLS

4
@ErikPorterは、HTMLを使用してください。また、stackoverflow.com
questions / 9234467 /…を

126

あなたはこのようなことをすることができます(少なくともMVC3では):

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

私がかみそりで引用を追加していると私が信じていたのは、実際にはブラウザーだ。MVC 4でテストしたときにRismが指摘したように(MVC 3ではテストしていませんが、動作は変更されていないと思います)、これは実際には生成されclass=TopBorderますが、ブラウザーはこれをうまく解析できます。HTMLパーサーは、欠落している属性の引用を多少許容しますが、スペースや特定の文字がある場合これは壊れる可能性があります

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

または

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

あなた自身の引用を提供することで何がうまくいかない

ネストされた引用に通常のC#規則を使用しようとすると、Razorが安全にエスケープしようとするため、見積もりよりも多くの引用ができてしまいます。例えば:

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

これ評価されるはずです<button type="button" style="border:0px">が、RazorはC#からのすべての出力をエスケープして、次のように生成します。

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

これは、ネットワーク経由で応答を表示した場合にのみ表示されます。HTMLインスペクタを使用する場合、実際のHTMLではなく、実際にはDOMが表示されることがよくあります。ブラウザはHTMLを解析してDOMに変換し、解析後のDOM表現にはすでにいくつかの優れた機能が適用されています。この場合、ブラウザは属性値の前後に引用符がないことを確認し、それらを追加します。

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

しかし、DOMインスペクターでは、HTML文字コードが正しく表示されるため、実際に次のように表示されます。

style=""border:0px""

Chromeでは、右クリックして[HTMLの編集]を選択すると元に戻り、厄介なHTML文字コードが表示されるため、実際の外部引用符とHTMLエンコードされた内部引用符があることがわかります。

したがって、自分で引用しようとする場合の問題は、Razorがこれらをエスケープすることです。

見積もりを完全に管理したい場合

Html.Rawを使用して引用がエスケープされないようにします。

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

としてレンダリング:

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

変数からHTMLを出力しないため、上記は完全に安全です。関係する唯一の変数は三項条件です。ただし、この最後の手法では、ユーザーが入力したデータから文字列を作成する場合に、特定のセキュリティ問題が発生する可能性があることに注意しください。たとえば、ユーザーが入力したデータに由来するデータフィールドから属性を構築した場合、Html.Rawを使用すると、文字列に属性とタグの途中の終わりが含まれる可能性があり、現在ログインしている代わりに何かを行うスクリプトタグを開始します。ユーザー(ログインしているユーザーと異なる場合があります)。たぶん、すべてのユーザーの写真のリストを含むページがあり、ツールチップを各ユーザーのユーザー名に設定し、1人のユーザーが自分の名前を付けている'/><script>$.post('changepassword.php?password=123')</script> そして今、このページを閲覧する他のすべてのユーザーのパスワードは、悪意のあるユーザーが知っているパスワードに即座に変更されます。


それはとても良い点です!そして実際には、ほとんどの状況で読みやすく、使いやすくなっています。
Dmytro Shevchenko

それが私の質問の例で私がやっていたことです。より詳細な説明と例をありがとう。:)
tony722

1
ただし、スペースには注意してください。「style = display:none;」なしとしてレンダリング; = "":= "" style = "display"
wmcainsh 2013年

1
では、なぜこれが機能しないのでしょうか。魔法の二重引用符<span @(true? "class = logo-owner":string.Empty)/> <span class = logo-owner />を生成するだけです
rism

1
@AaronLSはい、そうです。これはサーバーによって生成されたマークアップであるため、ブラウザー(Chrome 40 / FF33.1 / IE 10)がどのように影響するかを理解できません。影響がある場合は、2つのクラス属性のみで、askボタンのクラス属性やtype = 3つのボタンすべての「ボタン」属性。同じ結果のIE / Firefox / Chromeのために世界中に点在するいくつかのAzure仮想マシンにRDPすることもできるので、間違いなくサーバーのことです。
リズム、2015年

12

もう少し便利で構造化された方法は、Htmlヘルパーを使用することだと思います。あなたの見解では次のようになります:

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

@* ... *@

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

この方法が役立つ場合htmlAttrは、モデルにディクショナリを定義して、ビューに@{ }ロジックブロックが必要ないようにすることをお勧めします(より明確にしてください)。


4
-1、ビューにロジックを入れることを誰かに勧めないでください。これら2つのビューはレンダリングのみを担当します。代わりにHtmlHelperの例を追加してください。+ 1します。
jgauffin

1
物事をテストするために、ビューでコードブロックを使用できます-より高速です。そして、私の推奨は、このブロックをモデルに移動することでした。
Yaschur

3
はい。しかし、回答はベストプラクティスを示すものであり、コードのメンテナンスを悪夢のようにする迅速で汚いバージョンではないはずです。
jgauffin

@jgauffin Htmlヘルパーは不要だと思います。私の答えを見てください。
gdoronは

+1 @Yaschurあなたの答えは刺激的です。良い仕事を続けてください。すなわち。C#の明示的な変換機能を使用すると、この答えをさらに強化できます。すべてのコードを特定の方法で形成する必要はありませんでした。私たちが気づいていないより良い方法が常にあります。そして、いくつかのプロジェクトはコード編成を支持しています。コードの編成は、実際には概念ではありません。
Bamboo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.