Asp.Net MVC / Entity Framework. Avoid Soup Tag?

Good,

I have a new MVC project that uses an entity framework. I am spitting out messages (this is the bulletin board style section) now, depending on some conditional factors, the row in the table output should have a different class style.

The model that is passed to the page from the controller is the object model (messages called and contains the same fields as the database)

Now, to get the line styles, I did the following,

<%
               int i = 0;
               foreach (var message in ViewData.Model.MessageList)
               {
                   string className = "rowEven";

                   if (i % 2 == 0) { className = "rowOdd"; }
                   if (message.Deleted) { className = "deleted"; }
                   if (message.AuthorisedBy == null) { className = "notAuth"; }
                   if (message.Deleted) { className = "deleted"; }

           %>
                    <tr class="<%=className%>">
                        <td><%= Html.CheckBox("mc1")%></td>
                        <td>
                            <%= Html.ActionLink(message.Title, "Details", new { id = message.MessageID })%>
                        </td>
                        <td>User Name Here</td>
                        <td><%= Html.Encode(message.PublishDateTime.ToString())%></td>
                    </tr>                 
           <%
                   i++;
               } 
           %>

      

What's pretty ugly, there must be a better way to do this, any suggestions?

+2


source to share


4 answers


This is most definitely the logic of the view, and the view is where it belongs. However, you'd better move this CSS class selection code type assistant who will like Message

, and MessageList

:

public static string GetMessageCssClassName(this /* Don't remember :) */, Message message, MessageList messages)
{
    var cssClassName = messages.IndexOf(message) % 2  == 0 ?
        "rowOdd" : "rowEven";

    if(message.Deleted) cssClassName = "deleted";
    if(message.AuthorisedBy == null) cssClassName = "notAuth"; 
    if(message.Deleted) cssClassName = "deleted";
}

      



And now you can call this in yours <tr class="Html.GetMessageCssClassName(...)">

by getting rid of the counter i

:

<% foreach (var message in ViewData.Model.MessageList) { %>
    <tr class="<%= Html.GetMessageCssClassName(message, ViewData.Model.MessageList) %>">
        <td><%= Html.CheckBox("mc1")%></td>
        <td>
            <! -- Remaining stuff here -->
<% } %>

      

+5


source


I would recommend using model-view-viewmodel here. This allows you to encapsulate most of your logic in a viewmodel class, then you just call methods on your viewmodel instead of setting your logical line. this will make it look something like this ...

       <%  foreach (var messageViewModel in ViewData.Model.MessageList) { %>
                <tr class="<%=message.RowClass%>">
                    <td><%= Html.CheckBox("mc1")%></td>
                    <td>
                        <%= Html.ActionLink(message.Title, "Details", new { id = message.MessageID })%>
                    </td>
                    <td>User Name Here</td>
                    <td><%= Html.Encode(message.PublishedAt)%></td>
                </tr>                 
       <% } %>

      



As long as you get a lot more lessons, you get much more readable markup and your application is much more testable. It turns your view into a very simple window on your view model. The view model then encapsulates any logic and properties that are only needed for the view.

In response to your comment, here is an article that looks at Model Model - View - View Model in MVC. You just need to create a class with a bunch of properties and / or methods and fill that class with everything you need. Then pass the class to your view instead of passing the model directly. You can even use AutoMapper or another mapping framework to automatically map your models to your view models.

+2


source


How do I add additional helper methods? You can write your own extension methods in the base HtmlHelper class so you can write something like:

...
<tr class="<%= Html.GetMessageCssClass(i, message) %>">
...

      

+1


source


As mentioned, you can just write an extension method for your class Message

that is inside your Namespace.Site project (mvc project).

Something like:

public static class Extensions
{
    public static string CssClass(this Message message,int counter)
    {
        if (i % 2 == 0)
            return "rowOdd";
        else if (message.AuthorisedBy == null) 
            return "notAuth";    
        else if (message.Deleted) 
            return "deleted";

        return "rowEven";
    }
}

      

Using:

<tr class="<%=message.CssClass(i)%>">
    <td><%= Html.CheckBox("mc1")%></td>
    <td><%= Html.ActionLink(message.Title, "Details", new { id = message.MessageID })%></td>
    <td>User Name Here</td>
    <td><%= Html.Encode(message.PublishDateTime.ToString())%></td>
</tr> 

      

0


source







All Articles