我怎样才能避免在asp.net mvc视图中使用无法编写的代码

时间:2009-08-06 02:50:48

标签: asp.net asp.net-mvc views

我发现越来越多我的asp.net mvc视图开始看起来像我的旧的糟糕的asp代码,我无法维护或保持干净与集成< %%>和HTML放在一起。下面我有一个我正在谈论的代码sammple。是否有任何最佳实践或建议的方法来避免这种情况并保持视图更易于维护和可读。

            <td>
                <%
                    bool userRequiresApproval = false;
                    if (!string.IsNullOrEmpty(item.loginName))
                    {
                        MembershipUserCollection membership = (MembershipUserCollection)ViewData["UnapprovedUsers"];
                        if (membership != null && membership[item.loginName] != null)
                        {
                            userRequiresApproval = true;
                        }
                    }
                    bool isLoggedInUserAdmin = false;
                    if (ViewData.ContainsKey("isAdmin"))
                    {
                        isLoggedInUserAdmin = (bool)ViewData["isAdmin"];
                    }
                    if (isLoggedInUserAdmin && userRequiresApproval)
                    {%>
                        <%= Html.ActionLink("View", "Details", new { id=item.Mail_ID })%>, <%= Html.ActionLink("Delete", "GotoDeleteConfirmPage", new { id = item.Mail_ID })%>, <%= Html.ActionLink("Approve", "Approve", new { id = item.Mail_ID })%>
                    <%}
                    else if (isLoggedInUserAdmin)
                    {%>
                        <%= Html.ActionLink("View", "Details", new { id = item.Mail_ID })%>, <%= Html.ActionLink("Delete", "GotoDeleteConfirmPage", new { id = item.Mail_ID })%>
                    <%}
                    else
                    {%>
                        <%= Html.ActionLink("View", "Details", new { id = item.Mail_ID })%>
                    <%}%>
        </tr>
        <% } %>

3 个答案:

答案 0 :(得分:14)

我将首先解决具体问题,然后是摘要:

混凝土

一种可能的途径可能是创建一套Html帮助程序或用户控件,它们具有一些基本逻辑来确定它们是否应该可见。例如,您的用法可能是:

<td>
    Html.LinkList(", "
        ActionLinks.ViewDetails(item),
        ActionLinks.DeleteAndConfirm(item),
        ActionLinks.Approve(item))
</td>

每个操作都包含自己的逻辑,用于确定是否应该使用它(例如“我需要管理员权限”),如果该操作确定不符合自己的标准,则只需返回string.Empty

class ActionLinks
{
    public static string Approve(Item item)
    {
        if(ItemRequiresApproval(item) && CurrentUserIsAdmin())
        {
            return Html.ActionLink("Approve", "Approve", new { id = item.Mail_ID });
        }
        else
        {
            return string.Empty;
        }
    }

    private static bool ItemRequiresApproval(Item item)
    {
        //determine whether item requires approval
        //this could be further broken into a separate utilities class
    }

    private static bool CurrentUserIsAdmin()
    {
        //this should definitely go in a separate class dedicated to
        //handling membership and authorization
        //as well as figuring out who the current user is
    }
}

LinkList看起来像这样:

string LinkList(string delimiter, params string[] links)
{
    StringBuilder sb = new StringBuilder();
    foreach(string link in links)
    {
        if(!string.IsNullOrEmpty(link))
        {
            sb.Append(delimiter);
            sb.Append(link);
        }
    }
    return sb.ToString().Substring(delimiter.Length);
}

抽象

问题的解决方案在于记住SRP (Single Responsibility Principle)SOC (Separation of Concerns)。在您当前的示例中,您的View是一个类。您已使该类不仅对标记的整体结构负责,而且对几乎整个应用程序的每一分钟细节负责!您的视图不应该知道或关心管理员权限或批准。只有批准按钮才能知道批准。只有管​​理员特定的元素才应该知道管理员权限。如果您发现自己重复某些类型的检查(例如,“如果管理员显示x,否则显示y”),请创建一些通用包装器,如AdminPanel,它将自动打开或关闭。对于所有其他参与者而言,某个特定元素仅仅是或者不是 - 并且该元素有责任做出该决定。

答案 1 :(得分:1)

强大地键入您的视图,使用包含IsAdmin等内容的基类,如果不是控制器/操作特定的话,将有助于(甚至更容易地在会话中填充该数据)。

例如,您上面的整个代码可以合并到:

<tr><td>
<%
  Response.Write(Html.ActionLink("View", "Details", new { id=item.Mail_ID });
  if (Model.IsLoggedInUserAdmin)
  {
    Response.Write(", " + Html.ActionLink("Delete", "GotoDeleteConfirmPage", new { id = item.Mail_ID }));
  }
  if (Model.UserRequiresApproval)
  {
    Response.Write(", " + Html.ActionLink("Approve", "Approve", new { id = item.Mail_ID }));
  }
%>
</td></tr>

或者您可以将代码放在&lt; %%&gt;之间。进入一个控件并将所需的变量传递给RenderPartial,这样你的视图就不会被一堆Response.Write代码混乱,你原来的30行被合并为3(td,renderpartial,/ td)。无论哪种方式,你都会非常清楚地阐明你的观点。

答案 2 :(得分:1)

使用NHAML视图引擎 它可以帮助你做很多事情,并且可以节省很多打字。

另外(主要):

  • 将任何逻辑拉入控制器或模型
  • 使用键入的模型而不是ViewData
  • 使用类型化视图
  • 使用扩展方法
  • 使用部分观点