I heard that having @foreach inside of a view is a no-no. Meaning, the view should not have any logic in it. What is the best practice on where the logic for the @foreach should be at?
@foreach..
I heard that having @foreach inside of a view is a no-no. Meaning, the view should not have any logic in it. What is the best practice on where the logic for the @foreach should be at?
@foreach..
What is the best practice on where the logic for the @foreach should be at?
Nowhere, just get rid of it. You could use editor or display templates.
So for example:
@foreach (var item in Model.Foos)
{
<div>@item.Bar</div>
}
could perfectly fine be replaced by a display template:
@Html.DisplayFor(x => x.Foos)
and then you will define the corresponding display template (if you don't like the default one). So you would define a reusable template ~/Views/Shared/DisplayTemplates/Foo.cshtml
which will automatically be rendered by the framework for each element of the Foos collection (IEnumerable<Foo> Foos { get; set; }
):
@model Foo
<div>@Model.Bar</div>
Obviously exactly the same conventions apply for editor templates which should be used in case you want to show some input fields allowing you to edit the view model in contrast to just displaying it as readonly.
When people say don't put logic in views, they're usually referring to business logic, not rendering logic. In my humble opinion, I think using @foreach in views is perfectly fine.
I'm using @foreach
when I send an entity that contains a list of entities ( for example to display 2 grids in 1 view )
For example if I'm sending as model the entity Foo that contains Foo1(List<Foo1>)
and Foo2(List<Foo2>)
I can refer to the first List with:
@foreach (var item in Model.Foo.Foo1)
{
@Html.DisplayFor(modelItem=> item.fooName)
}
a reply to @DarinDimitrov for a case where i have used foreach in a razor view.
<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>
The answer will not work when using the overload to indicate the template @Html.DisplayFor(x => x.Foos, "YourTemplateName)
.
Seems to be designed that way, see this case. Also the exception the framework gives (about the type not been as expected) is quite misleading and fooled me on the first try (thanks @CodeCaster)
In this case you have to use @foreach
@foreach (var item in Model.Foos)
{
@Html.DisplayFor(x => item, "FooTemplate")
}