как я могу избежать неуправляемого кода в asp.net mvc views - PullRequest
6 голосов
/ 06 августа 2009

Я все больше нахожу, что мои представления mvc asp.net начинают выглядеть как мой старый дерьмовый код asp, который я никогда не смогу поддерживать или поддерживать в чистоте с помощью встроенного <%%> и html, вместе взятых. ниже у меня есть пример кода того, о чем я говорю. Есть ли лучшая практика или рекомендуемый способ избежать этого и сделать представления более понятными и понятными.

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

14 голосов
/ 06 августа 2009

Сначала я рассмотрю конкретный вопрос, а затем реферат:

Бетон

Одним из возможных путей может быть создание набора помощников 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 (Принцип единой ответственности) и SOC (Разделение проблем) . В вашем текущем примере ваш View - это класс. Вы сделали этот класс ответственным не только за общую структуру разметки, но и за каждую мелкую деталь почти всего вашего приложения! Ваше мнение не должно знать или заботиться о правах администратора или одобрении. Только кнопки подтверждения должны знать об утверждении. Только элементы, которые являются специфическими для администратора, должны знать о правах администратора. Если вы обнаружите, что повторяете определенные виды проверок (например, «если администратор показывает x, иначе показывает y»), создайте некоторые общие обертки, такие как AdminPanel, которые будут соответствующим образом включаться или выключаться. Для всех остальных игроков данный элемент просто является или не является - и именно этот элемент несет ответственность за принятие этого решения.

1 голос
/ 06 августа 2009

Использовать движок просмотра NHAML.
Это поможет вам во многих вещах и сэкономит много печатать.

Дополнительно (и в основном):

  • Вставьте любую логику в контроллер или модель
  • Использовать типизированную модель вместо ViewData
  • Использовать типизированные представления
  • Использовать методы расширения
  • Использовать частичные представления
1 голос
/ 06 августа 2009

Строгая типизация ваших представлений с базовым классом, содержащим такие вещи, как 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>

Или вы можете поместить код между <%%> в элемент управления и передать необходимые переменные в RenderPartial, чтобы ваше представление не загромождалось связкой кода Response.Write и вашим исходным кодом 30. линии объединены в 3 (тд, рендеринг, / тд). В любом случае, вы очень сильно проясните свое мнение.

...