Razor MVC3를 사용하는 조건부 HTML 속성


100

변수 strCSSClass는 종종 값을 갖지만 때로는 비어 있습니다.

이 입력 요소의 HTML에 빈 class = ""를 포함하고 싶지 않습니다. 즉, strCSSClass가 비어 있으면 class = 속성이 전혀 필요하지 않습니다.

다음은 조건부 HTML 속성을 수행하는 한 가지 방법입니다.

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

이 작업을 수행하는 더 우아한 방법이 있습니까? 특히 요소의 다른 부분에서 사용되는 것과 동일한 구문을 따를 수있는 경우 : class = "@ strCSSClass"?

답변:


160

Razor의 PM 인 저 에게서는 듣지 못했지만 Razor 2 (웹 페이지 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)"
Erik Porter

1
이것이 MVC 4에서 성공적으로 작동 함을 나타내는 메모를 추가했습니다. MVC 3을 사용하는 경우 아래 내 대답을 참조하십시오.
AaronLS

4
@ErikPorter 내 HTML로 메시지를 보내지 마십시오! 또한 stackoverflow.com/questions/9234467/… 을 참조하십시오. 이것은 다른 나쁜 행동에 대해서도 마찬가지입니다
eaglestorm

126

다음과 같이 할 수 있습니다 (최소한 MVC3에서는).

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

내가 따옴표를 추가하는 면도칼이라고 생각한 것은 실제로 브라우저였습니다. Rism이 MVC 4로 테스트 할 때 지적했듯이 (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">하지만, 면도기는 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를 사용하면 문자열에 속성과 태그의 조기 종료가 포함될 수 있으며 현재 로그인 한 사용자를 대신하여 작업을 수행하는 스크립트 태그를 시작할 수 있습니다. 사용자 (로그인 한 사용자와 다를 수 있음). 모든 사용자 사진 목록이있는 페이지가 있고 각 사용자의 사용자 이름이되는 도구 설명을 설정하고 한 명의 사용자가 자신의 이름을 지을 수 있습니다.'/><script>$.post('changepassword.php?password=123')</script> 이제이 페이지를 보는 다른 사용자는 악의적 인 사용자가 알고있는 암호로 즉시 암호를 변경하게됩니다.


아주 좋은 점입니다! 그리고 실제로 대부분의 상황에서 읽고 사용할 수 있습니다.
Dmytro Shevchenko

그것이 내 질문의 예에서 내가하고 있었던 일입니다. 더 자세한 설명과 예를 들어 주셔서 감사합니다. :)
tony722

1
그래도 공백을 조심하십시오. "스타일 = 표시 : 없음;"
renders

1
그런데 왜하지 않습니다이 작업 재 : 마법 따옴표 <스팬 @ (사실 "클래스 = 로고 소유자": String.Empty로) /> 그것은 단지 생산 <스팬 클래스 = 로고 소유자 />
rism

1
@AaronLS 네, 정확히 그렇습니다. 이것이 서버 생성 마크 업이기 때문에 브라우저 (Chrome 40 / FF33.1 / IE 10)가 어떤 영향을 미치는지 이해할 수 없으며, 그렇다면 두 가지 클래스 속성 만 제공되지만 요청 버튼의 클래스 속성 또는 type = 세 버튼 모두의 "버튼"속성. 동일한 결과 IE / Firefox / Chrome을 위해 전 세계에있는 두 개의 Azure 가상 머신으로 RDP를 수행 할 수 있기 때문에 IMHO라는 것은 확실히 서버입니다.
rism

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, 뷰에 논리를 넣도록 누군가를 추천하지 마십시오. Thew 뷰는 렌더링 만 담당해야합니다. 대신 HtmlHelper 예제를 추가하면 +1을 드리겠습니다.
jgauffin 2011

1
사물을 테스트하기 위해보기에서 코드 블록을 사용할 수 있습니다. 더 빠릅니다. 제 추천은이 블록을 모델로 옮기는 것이 었습니다.
Yaschur 2011

3
예, 그러나 답변은 코드 유지 관리를 악몽으로 만드는 빠르고 더러운 버전이 아닌 모범 사례를 보여야합니다.
jgauffin 2011

@jgauffin 여기 Html 도우미가 불필요하다고 생각합니다. 내 대답을 참조하십시오.
gdoron 모니카 지원하고

+1 @Yaschur 귀하의 답변은 고무적입니다. 좋은 일을 계속하십시오. 즉. C # 명시 적 변환 기능을 사용하면이 답변을 더욱 향상시킬 수 있습니다. 모든 코드가 특정 방식으로 형성되어야하는 것은 아닙니다. 우리가 알지 못하는 더 나은 방법이 항상 있습니다. 그리고 일부 프로젝트는 코드 구성을 선호합니다. 코드 구성은 실제로 개념이 아닙니다!
Bamboo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.