views:

156

answers:

3

Here's a simple MVC View that displays all Areas in a DB and then lists all Carreras in each Area under the header.

<h2>Listado General de Carreras</h2>

    <% foreach (var Area in (List<string>)ViewData["Areas"])
       { %>

       <p><span class="titulo"><%: Area%></span></p>

       <% foreach (var carrera in Model)
          {
              if (carrera.Area.Nombre == Area)
              { %>    

                <p><%=Html.ActionLink(carrera.Nombre, "Details", new { id = carrera.ID })%></p>

            <% }

          }
       }%>

Do you think you can make this code a bit prettier/efficient?

+1  A: 

I don't think you need to pass the Areas in the ViewData. Sort your Model by Area. Then you just need a single loop through Model and you can check if carrera.Area.Nombre is different from the last one you saw, and if so, print out the header for it.

Hopefully that makes sense, but let me know if you need a nudge with code.

rchern
A: 

Kind of hard to tell without knowing what exactly is Area. But if it is possible, I would move areas into the view model, and make each Area object have collection of carreras.

Also to make the action link prettier you can use T4MVC.

You could end up with code like this:

<h2>Listado General de Carreras</h2>

<% foreach (var area in Model.Areas) { %>

    <p><span class="titulo"><%:area %></span></p>

    <% foreach (var carrera in area) { %>
        <p><%:Html.ActionLink(carrera.Nombre, MVC.Carrera.Details(carrera.ID)) %></p>
    <% } %>

<% } %>
Necros
I agree with the T4MVC suggestion. I've been using it and it makes the code more readable and gets rid of those terrible magic strings in the views.
Jeff T
A: 

You could get rid of the if(crrera.Area.Nombre == Area) with Linq. From the look of it your Model is some type of IEnumerable so your inner loop would become

<% foreach var carrera in Model.Where(c => c.Area.Nombre == Area))
{ %>
    <p><%= Html.ActionLink(carrera.Nombre, "Details", new { id = carrera.ID })%></p>
<% } %>

This wouldn't really help with "efficiency" but it is definitely "prettier" IMHO

Couple of MVC 3 features would also help on the prettiness front. First the Razor syntax, and second the new ViewModel property is of type dynamic so you'd get rid of the nasty dictionary lookup on ViewData and its associated cast i.e. your outer loop would become

<% foreach (var Area in View.Areas)
} %>

You could achieve something similar by creating a view specific model and tacking the Areas property on to that model

Simon Fox
Thanks, I saw MVC3 last night and I can't wait for it! It seems pretty nice to use. :P
Sergio Tapia
Why not go for pretty and effective instead of just pretty? You **can** have both.
rchern
@rchern don't know where you got effective from...this does exactly what the OP asked for so it is effective. As for efficiency, I would argue that any gain achieved by removing the `if` block of the inner loop is negligible and thats why I say it "wouldn't really help"...I'll leave it to those much smarter than me to explain a concept you should familiarize yourself with http://c2.com/cgi/wiki?PrematureOptimization
Simon Fox
@rchern On that note I could give your answer a downvote as well as 1) you won't get the same result as the OPs code (what if he wants areas with no careers to still have a header printed) and 2) its definitely not prettier and probably no more efficient than what the OP has provided
Simon Fox
@rchern but I won't because that would just be silly
Simon Fox