MVC Razor @foreach


79

Tôi nghe nói rằng có @foreach bên trong chế độ xem là điều không nên. Có nghĩa là, khung nhìn không nên có bất kỳ logic nào trong đó. Thực tiễn tốt nhất về vị trí logic cho @foreach nên ở đâu?

    @foreach.. 

5
Bạn đã đọc nó ở đâu? Logic là những gì dao cạo có nghĩa là!
Nicholas King

4
vui lòng đọc ms làm theo hướng dẫn asp.net/web-pages/tutorials/basics/...
Nicholas Vua

Câu trả lời:


159

Thực tiễn tốt nhất về vị trí logic cho @foreach nên ở đâu?

Không đâu, chỉ cần thoát khỏi nó. Bạn có thể sử dụng trình chỉnh sửa hoặc các mẫu hiển thị.

Ví dụ:

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

hoàn toàn có thể được thay thế bằng một mẫu hiển thị:

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

và sau đó bạn sẽ xác định mẫu hiển thị tương ứng (nếu bạn không thích mẫu mặc định ). Vì vậy, bạn sẽ xác định một mẫu có thể sử dụng lại ~/Views/Shared/DisplayTemplates/Foo.cshtmlsẽ tự động được khung hiển thị cho từng phần tử của Foos collection ( IEnumerable<Foo> Foos { get; set; }):

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

Rõ ràng là chính xác các quy ước giống nhau áp dụng cho các mẫu trình soạn thảo nên được sử dụng trong trường hợp bạn muốn hiển thị một số trường đầu vào cho phép bạn chỉnh sửa mô hình chế độ xem trái ngược với việc chỉ hiển thị nó ở dạng chỉ đọc.


3
@DarinDimitrov thats đúng nếu nó là một mô hình MVC nghiêm ngặt bạn đang mã hóa chống lại tuy nhiên nếu một tình huống phát sinh nơi một bộ sưu tập cần được looped qua mà không có trong các mô hình, tôi không thấy một vấn đề với việc sử dụng foreach
Nicholas Vua

6
@NicholasKing, trường hợp như vậy không bao giờ nên phát sinh. Chế độ xem không được chạm vào bất kỳ thứ gì khác ngoài những gì hiện có trong mô hình chế độ xem được chuyển bởi hành động của bộ điều khiển. Nếu nó không có trong mô hình khung nhìn thì bạn nên đặt nó vào đó nếu khung nhìn cần nó. Đó chính xác là những gì mà các mô hình xem có ý nghĩa.
Darin Dimitrov

1
@MihaiLabo, vâng, đó là những gì tôi đang nói.
Darin Dimitrov

2
Điều gì sẽ xảy ra nếu loại phần tử trong bộ sưu tập không đủ để xác định hiển thị? Ví dụ: mô hình của tôi có một tập hợp các chuỗi, nhưng đôi khi tôi muốn có một chuỗi trên mỗi dòng và trong trường hợp khác, tôi muốn chúng được phân tách bằng dấu phẩy?
Marc Stober,

6
Vì vậy, vấn đề chính xác là foreachgì? Ít nhất thì một mẫu hiển thị (trong khi một cách tiếp cận hoàn toàn có thể chấp nhận được, bất kể) yêu cầu một chế độ xem mới được hiển thị, điều này không miễn phí. Phần lớn thời gian nó sẽ không ảnh hưởng đáng kể đến thời gian tải trang web của bạn, nhưng nếu thực hiện đủ, nó có thể gây ra hiệu suất. Một foreachchút về HTML luôn và sẽ gần như ngay lập tức. Như tôi đã nói, nó không phải là một vấn đề lớn, mặc dù vậy, nhưng nếu có bất cứ điều gì có một lý lẽ để sử dụng foreach.
Chris Pratt

96

Khi mọi người nói rằng đừng đưa logic vào các khung nhìn, họ thường đề cập đến logic nghiệp vụ, không phải logic hiển thị. Theo ý kiến ​​khiêm tốn của tôi, tôi nghĩ việc sử dụng @foreach trong lượt xem là hoàn toàn tốt.


21
Đã đồng ý. Nhắc tôi về các cuộc tranh luận HTML ngữ nghĩa cũ, cuối cùng dẫn đến việc mọi người cố gắng sử dụng div và CSS để tạo một "bảng" cho dữ liệu dạng bảng thực tế, bởi vì chúng rất phản bảng.
Chris Pratt

1
Tôi đồng ý. Con người rất tệ khi định hướng sai. Tôi có thực sự cần một thư mục mới, với chế độ xem mới, chỉ để hiển thị mọi thứ trong danh sách trong mô hình xem của tôi không?
Don Cheadle

1
Việc sử dụng div / css để tạo chế độ xem dữ liệu dạng bảng có cần thiết để tạo chế độ xem đáp ứng không?
frostshoxx

13

Tôi đang sử dụng @foreachkhi tôi gửi một thực thể có chứa danh sách các thực thể (ví dụ: để hiển thị 2 lưới trong 1 chế độ xem)

Ví dụ: nếu tôi đang gửi dưới dạng mô hình thực thể Foo chứa Foo1(List<Foo1>)Foo2(List<Foo2>)

Tôi có thể tham khảo Danh sách đầu tiên với:

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

11

một câu trả lời cho @DarinDimitrov cho trường hợp tôi đã sử dụng foreach trong chế độ xem dao cạo.

<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
WOW người đàn ông, bạn sẽ viết một cái gì đó như thế này trong một lượt xem? Tại sao không viết một trình trợ giúp tùy chỉnh có thể tái sử dụng Html.DropDownListForsẽ chỉ đơn giản là tính đến tiêu đề? Đó là tầm thường và không bật quan điểm của bạn vào mã spaghetti: stackoverflow.com/a/7938038/29407
Darin Dimitrov

7
@DarinDimitrov vâng, chúng tôi làm việc trong một môi trường rất linh hoạt, có nghĩa là các tình huống như thế này đôi khi ngăn chúng tôi sử dụng những thứ như DropDownF Vì chúng tôi không luôn có yêu cầu được xác định rõ ràng. Tôi tin rằng trong trường hợp này trình đơn thả xuống ban đầu không cần "tất cả" sau đó nó đã làm nhưng chỉ trong một DropDown trên chế độ xem. Vì trang này sử dụng ajax để cập nhật mẫu MVC không nghiêm ngặt và bạn không thể tải sản phẩm lên tất cả các danh mục theo yêu cầu. Không lý tưởng nhưng đôi khi không thể tránh khỏi.
Nicholas King

Có lẽ một ví dụ tốt hơn sẽ là sử dụng điều này để kết xuất optgroup các phần tử trong danh sách được chọn, vì không có hỗ trợ cho điều đó trong HtmlHelpers. Nếu bạn chỉ cần thêm một mục bổ sung vào danh sách đã chọn, có nhiều cách tốt hơn để đạt được điều đó và sau đó vẫn sử dụng trình trợ giúp.
Chris Pratt

Đó sẽ không phải là định nghĩa của tôi về Agile - Tôi phải đồng ý với @DarinDimitrov
Luis Filipe

3

Câu trả lời sẽ không hoạt động khi sử dụng quá tải để chỉ ra mẫu @Html.DisplayFor(x => x.Foos, "YourTemplateName).

Có vẻ như được thiết kế theo cách đó, hãy xem trường hợp này . Ngoài ra, ngoại lệ mà khuôn khổ đưa ra (về loại không được như mong đợi) khá gây hiểu lầm và đánh lừa tôi trong lần thử đầu tiên (cảm ơn @CodeCaster)

Trong trường hợp này bạn phải sử dụng@foreach

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

Câu trả lời đó được viết bởi một người làm việc trên MVC, vì vậy tôi đoán họ biết họ đang nói gì. MVC sẽ lặp lại IEnumerable<T>và gọi mẫu cho kiểu Tcho mỗi phần tử.
CodeCaster

Về chỉnh sửa của bạn: đó là mã của bạn sai hoặc lỗi trong phiên bản MVC cụ thể đó (trong 5.2.2, nó hoạt động với tôi). Nó phải hoạt động như mô tả trong câu trả lời được chấp nhận. Thay vì nói điều đó là sai, hãy mở câu hỏi của riêng bạn về vấn đề này nếu bạn muốn.
CodeCaster

@CodeCaster Tôi tin rằng phản hồi của tôi bổ sung thêm một số thông tin cần thiết cho trường hợp cụ thể đó (nó đã lãng phí một chút thời gian của tôi để tìm ra điều gì đã xảy ra). Bạn có thể vui lòng thêm một số giải thích cho việc giữ phiếu giảm giá không? (cảm ơn vì thời gian của bạn btw, chỉ muốn đi đến tận cùng của mọi thứ)
Tiberiu Craciun

Tôi không nghĩ đó là một câu trả lời hay vì nó không xác minh lỗi, điều này giúp cho những tin đồn trên thế giới như "Một DisplayTemplate không thể lặp lại" - nó được cho là vậy, vì vậy nó sẽ hoạt động. Nếu nó thực sự không xảy ra, hãy gửi một lỗi và thay vào đó mở một câu hỏi riêng biệt trong đó bạn tái tạo vấn đề và đề cập rằng phiên bản cụ thể này, trái ngược với phần Hỏi & Đáp xử lý những gì thường xảy ra.
CodeCaster

@CodeCaster Tôi đã có một chỉnh sửa khác trong khi đó sau khi tôi hiểu trường hợp cụ thể của mình (tôi đã thay đổi toàn bộ bài đăng). Trong lần chỉnh sửa cuối cùng của tôi, tôi đã chỉ ra điều kiện chính xác khi câu trả lời được chấp nhận không áp dụng với liên kết dự phòng cho một câu hỏi liên quan được trả lời bởi cùng một người chứng minh đó là do thiết kế chứ không phải lỗi.
Tiberiu Craciun
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.