Asp.Net MVC /实体框架。避免标签汤?

时间:2009-10-06 09:59:33

标签: asp.net-mvc entity-framework tag-soup

确定,

我有一个使用实体框架的新MVC项目。我正在吐出消息(这是一个公告板样式部分),现在根据一些条件因素,表输出中的行必须具有不同的类样式。

从控制器传递到页面的模型是实体模型(称为消息并包含与数据库相同的字段)

现在,为了获得行样式,我做了以下内容,

<%
               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++;
               } 
           %>

哪个非常难看,必须有更好的方法来做这个,有什么建议吗?

4 个答案:

答案 0 :(得分:5)

这绝对是表示逻辑,视图属于它。但是,您最好将CSS类选择代码移动到视图助手,它将同时接受MessageMessageList

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";
}

现在你可以在你的<tr class="Html.GetMessageCssClassName(...)">中调用它,摆脱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 -->
<% } %>

答案 1 :(得分:2)

我建议在这里使用model-view-viewmodel。这允许您将大量逻辑封装在视图模型类中,然后只需在视图模型上调用方法,而不是将逻辑内联。这会让它看起来像这样......

       <%  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>                 
       <% } %>

虽然您最终会获得更多类,但您可以获得更多可读标记,并且您的应用程序更易于测试。它将您的视图转换为视图模型上的一个非常简单的窗口。然后,视图模型封装了视图所需的任何逻辑和属性。

回复您的评论here是一篇文章,介绍MVC中的模型 - 视图 - 视图模型模式。您只需要创建一个包含一堆属性和/或方法的类,并使用您需要的所有内容填充此类。然后将类传递给您的视图,而不是直接传递模型。您甚至可以使用AutoMapper或其他映射框架自动将模型映射到视图模型。

答案 2 :(得分:1)

添加一些辅助方法怎么样?您可以将自己的扩展方法编写到基础HtmlHelper类中,这样就可以编写类似:

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

答案 3 :(得分:0)

正如很多人已经提到过的,你可以为你的Namespace.Site项目(mvc项目)中的Message类编写一个扩展方法。

类似的东西:

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";
    }
}

用法:

<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>