MVC 면도기 @foreach


82

뷰 내부에 @foreach가있는 것은 안된다고 들었습니다. 의미, 뷰에는 논리가 없어야합니다. @foreach에 대한 논리가 있어야하는 위치에 대한 모범 사례는 무엇입니까?

    @foreach.. 

5
어디서 읽었습니까? 논리는 면도기가 의미하는 것입니다!
Nicholas King

4
다음 MS를 참조하시기 바랍니다 튜토리얼 asp.net/web-pages/tutorials/basics/...
니콜라스 왕

답변:


162

@foreach에 대한 논리가 있어야하는 위치에 대한 모범 사례는 무엇입니까?

아무데도 그냥 제거하십시오. 편집기 또는 디스플레이 템플릿을 사용할 수 있습니다.

예를 들면 다음과 같습니다.

@foreach (var item in Model.Foos)
{
    <div>@item.Bar</div>
}

디스플레이 템플릿으로 완벽하게 대체 할 수 있습니다.

@Html.DisplayFor(x => x.Foos)

그런 다음 해당 디스플레이 템플릿을 정의합니다 ( 기본 템플릿이 마음에 들지 않는 경우 ). 따라서 ~/Views/Shared/DisplayTemplates/Foo.cshtmlFoos 컬렉션 ( IEnumerable<Foo> Foos { get; set; }) 의 각 요소에 대해 프레임 워크에서 자동으로 렌더링 할 재사용 가능한 템플릿 을 정의합니다 .

@model Foo
<div>@Model.Bar</div>

읽기 전용으로 표시하는 것과 달리보기 모델을 편집 할 수있는 일부 입력 필드를 표시하려는 경우 사용해야하는 편집기 템플릿에 대해 정확히 동일한 규칙이 적용됩니다.


3
@DarinDimitrov 그것은 당신이 코딩하는 엄격한 MVC 모델이라면 사실이지만, 모델에없는 컬렉션을 반복해야하는 상황이 발생하면 foreach 사용에 문제가 없습니다
Nicholas King

6
@NicholasKing, 그런 상황이 발생해서는 안됩니다. 뷰는 컨트롤러 액션에 의해 전달 된 뷰 모델에 존재하는 것 이외의 것을 건 드리면 안됩니다. 뷰 모델에없는 경우 뷰에 필요하면 거기에 넣어야합니다. 그것이 바로 뷰 모델이 의미하는 바입니다.
Darin Dimitrov

1
@MihaiLabo, 네, 그게 제가 말하는 것입니다.
Darin Dimitrov 2012

2
컬렉션의 요소 유형이 디스플레이를 결정하기에 충분하지 않으면 어떻게됩니까? 예를 들어, 내 모델에는 문자열 모음이 있지만 때로는 한 줄에 하나의 문자열을 원하고 다른 경우에는 쉼표로 구분하고 싶습니까?
Marc Stober 2014 년

6
그렇다면 정확히 무엇이 문제 foreach입니까? 최소한 디스플레이 템플릿 (완벽하게 허용되는 접근 방식은 상관없이)에는 렌더링 할 새 뷰가 필요하며 이는 무료가 아닙니다. 대부분의 경우 사이트로드 시간에 눈에 띄게 영향을주지 않지만 충분히 수행하면 성능 저하가 발생할 수 있습니다. foreachHTML의 주위에 비트가 항상 거의 순간 일 것이다. 내가 말했듯이,하지만 큰 거래 중 하나의 방법은 아니지만, 어떤 경우 인수 거기 에 대한 사용 foreach.
크리스 프랫

98

사람들이 뷰에 로직을 넣지 않는다고 말할 때 그들은 일반적으로 로직을 렌더링하는 것이 아니라 비즈니스 로직을 참조합니다. 겸손한 의견으로는 뷰에서 @foreach를 사용하는 것이 완벽하다고 생각합니다.


22
동의합니다. 예전의 의미 론적 HTML 논쟁이 떠 오릅니다. 결국 사람들은 div와 CSS를 사용하여 실제 테이블 형식 데이터를위한 "테이블"을 만들려고했습니다.
Chris Pratt

1
나는 동의한다. 인간은 잘못된 방향을 잘 모릅니다. 내 viewmodel의 목록에 항목을 표시하기 위해 새보기가있는 새 폴더가 정말로 필요합니까?
Don Cheadle

1
div / css를 사용하여 표 형식 데이터보기를 만드는 것이 반응 형보기를 만드는 데 필요하지 않습니까?
frostshoxx

13

나는 사용하고있다 @foreach엔터티 목록이 포함 된 엔터티를 보낼 때 하고 있습니다 (예 : 1 개의보기에 2 개의 그리드 표시).

예를 들어 내가 모델로 포함하는 엔티티 푸를 보낸다 경우 Foo1(List<Foo1>)Foo2(List<Foo2>)

다음과 같이 첫 번째 목록을 참조 할 수 있습니다.

@foreach (var item in Model.Foo.Foo1)
{
    @Html.DisplayFor(modelItem=> item.fooName)
}

11

면도기보기에서 foreach를 사용한 경우 @DarinDimitrov에 대한 답장.

<li><label for="category">Category</label>
        <select id="category">
            <option value="0">All</option>
            @foreach(Category c in Model.Categories)
            {
                <option title="@c.Description" value="@c.CategoryID">@c.Name</option>
            }
        </select>
</li>

6
와우, 당신은보기에서 이와 같은 것을 쓸 것입니까? Html.DropDownListFor단순히 제목 만 고려 하는 재사용 가능한 사용자 지정 도우미를 작성하지 않겠습니까? 그것은 사소한 스파게티 코드로 뷰를 설정하지 않습니다 stackoverflow.com/a/7938038/29407
대린 디미트로프

7
@DarinDimitrov 예, 우리는 매우 민첩한 환경에서 작업합니다. 즉, 이와 같은 시나리오는 때때로 명확하게 정의 된 요구 사항이 없기 때문에 DropDownFor와 같은 것을 사용하지 못하게합니다. 이 경우 드롭 다운이 처음에는 "모두"가 필요하지 않았고보기에 드롭 다운이 하나만 필요하다고 생각합니다. 이 페이지는 ajax를 사용하여 엄격한 MVC 패턴이 아닌 패턴을 업데이트하고 요구 사항에 따라 모든 카테고리에 제품을 업로드 할 수 없습니다. 이상적이지는 않지만 때로는 피할 수 없습니다.
Nicholas King

optgroupHtmlHelpers에는 지원이 없기 때문에 선택 목록의 요소 를 렌더링하는 데 더 좋은 예가 될 수 있습니다 . 선택 목록에 추가 항목을 추가해야하는 경우이를 달성 한 다음 도우미를 계속 사용하는 더 좋은 방법이 있습니다.
Chris Pratt

즉 애자의 내 정의되지 않을 것 - 나는 @DarinDimitrov에 동의해야
루이스 필리페

3

템플릿을 나타 내기 위해 오버로드를 사용하면 대답 이 작동하지 않습니다 @Html.DisplayFor(x => x.Foos, "YourTemplateName).

그런 식으로 설계된 것 같습니다 . 이 사례를 참조하십시오 . 또한 프레임 워크가 제공하는 예외 (예상과 다른 유형에 대한)는 매우 오해의 소지가 있으며 첫 번째 시도에서 나를 속였습니다 (@CodeCaster에게 감사드립니다)

이 경우 당신은에있는 사용@foreach

@foreach (var item in Model.Foos)
{
    @Html.DisplayFor(x => item, "FooTemplate")
}

그 대답은 MVC에서 일하는 사람이 작성한 것이므로 그들이 말하는 것을 알고 있다고 생각합니다. MVC는 각 요소의 IEnumerable<T>유형에 T대한 템플릿을 반복 하고 호출합니다 .
CodeCaster 2015 년

편집과 관련하여 : 귀하의 코드가 잘못되었거나 특정 MVC 버전의 버그입니다 (5.2.2에서는 저에게 적합합니다). 수락 된 답변에 설명 된대로 작동해야합니다. 틀렸다고 말하는 대신 원하는 경우 문제에 대한 자신의 질문을여십시오.
CodeCaster 2015-09-05

@CodeCaster 나는 내 응답이 특정 경우에 대한 몇 가지 경고를 추가한다고 생각합니다 (무엇이 잘못되었는지 알아내는 데 시간을 낭비했습니다). 반대표 유지에 대한 설명을 추가해 주시겠습니까? (시간 내 주셔서 감사합니다 BTW, 단지 사물의 바닥에 도달 할)
Tiberiu Craciun

나는 그것이 버그를 확인하지 않기 때문에 좋은 대답이라고 생각하지 않는다. 이것은 "A DisplayTemplate은 반복 할 수 없다"와 같은 세상의 소문을 돕는다. 실제로 그렇지 않은 경우 버그를 신고하고 문제를 재현하는 별도의 질문을 열고이 특정 버전을 언급하십시오. 일반적으로 발생해야하는 작업을 처리하는 Q & A가 아닙니다.
CodeCaster

@CodeCaster 나는 내 특정 사례를 이해 한 후에 다른 편집을했습니다 (전체 게시물을 변경했습니다). 마지막 편집에서 나는 승인 된 답변이 버그가 아닌 의도적으로 증명 된 동일한 사람이 답변 한 관련 질문에 대한 백업 링크와 함께 적용되지 않는 정확한 조건을 표시했습니다.
Tiberiu Craciun 2015 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.