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.