Маршрут навигации ASP.NET MVC, который изменяется в зависимости от просматриваемых данных - PullRequest
1 голос
/ 12 октября 2010

Я нахожусь в процессе создания вкладок навигации, где местоположение маршрута может меняться. Параметр, используемый для отображения вкладок, должен основываться на просматриваемых в настоящее время данных (которые, если он пользователь, могут не быть зарегистрированным пользователем).

В примере изображения это пользователь. Поэтому, если я смотрю на Эндрю Стила, то ссылки должны быть контекстуальными с Эндрю Стилом (резюме Эндрю, компьютеры, учетные записи и т. Д.). Когда я смотрю на Брюса Хэмилтона, ссылки должны быть контекстными с Брюсом Хэмилтоном (резюме Брюса, компьютеры, аккаунты и т. Д.).

Example of Tabbed Navigation

Я решил эту проблему, вставив необходимое значение параметра в каждую ViewModel, а затем передав значение в частичное для визуализации ссылок; это чувствует себя грязным. Я бы предпочел не помещать данные параметров связывания в каждую модель представления. Было бы разумно использовать Html.Action или Html.RenderAction в сочетании со значением словаря ViewData, но я стараюсь избегать использования "магических строк", где это возможно.

Есть ли лучший способ получить значение параметра для представления, которое мне не хватает?

Ответы [ 4 ]

1 голос
/ 12 октября 2010

Лично я бы использовал RenderAction из фьючерсов MVC или частичный вызов рендеринга в зависимости от требований к производительности и вкуса.

Преимущество RenderAction заключается в том, что вам не нужно передавать все необходимые данные рендеринга в действие контроллера делегата, поскольку оно может выполнять сам поиск. В то время как для частичного просмотра на главной странице должно быть достаточно данных для отображения вкладки. В любом случае это всего два цикла for (один для списка вкладок, один для отображения вкладок) и немного дополнительных данных в вашей модели.

1 голос
/ 12 октября 2010

Для этого вы можете создать модель представления, которая предоставляет предпочтения вкладки.Если каждая вкладка полностью отличается, у вас может быть базовый класс viewmodel, который предоставляет предпочтение вкладке, и каждая вкладка может иметь свою собственную модель представления.

1 голос
/ 12 октября 2010

Некоторое время назад я написал сайт, где у меня были разные вкладки, которые переходили в разные места для разных пользователей. Я проведу вас через мое решение, надеюсь, я правильно понял вопрос, и это поможет.

Что касается получения данных в и из View, я использую ViewDataDictionary. Насколько я знаю, это то, что нужно, когда ваша модель не состоит из одного простого объекта. Чтобы обойти «волшебные строки» ключей представления, я создаю несколько методов расширения в ViewDataDictionary. Это имеет тот недостаток, что вы заканчиваете множеством дополнительных методов, но по крайней мере все ваши строковые ключи изолированы в одном месте. Вы могли бы даже сделать дополнительный шаг создания констант в классе, но это кажется излишним, когда только этот класс использует их. Свойства расширения были бы лучше, но ...

/// <summary>
/// Gets the list of tabs to show.
/// </summary>
/// <param name="dictionary"></param>
/// <returns></returns>
public static IList<TabItemDisplay> TabListGet(this ViewDataDictionary dictionary)
{
    IList<TabItemDisplay> result;
    if (dictionary.ContainsKey("TabList"))
        result = dictionary["TabList"] as IList<TabItemDisplay>;
    else
        result = null;
    return result;
}

/// <summary>
/// Sets the list of tabs to show.
/// </summary>
/// <param name="dictionary"></param>
/// <param name="tabList"></param>
/// <returns></returns>
public static IList<TabItemDisplay> TabListSet(this ViewDataDictionary dictionary, IList<TabItemDisplay> tabList)
{
    dictionary["TabList"] = tabList;
    return tabList;
}

Вы заметите, что у меня есть явный объект просмотра, TabItemDisplay, который я передаю в словарь. Он содержит все значения, необходимые для передачи в Html.ActionLink.

public class TabItemDisplay
{
    public string Name { get; set; }
    public string Action { get; set; }
    public string Controller { get; set; }
    public object RouteValues { get; set; }
}

Поскольку это представление не является основным содержимым страницы, я предпочитаю поместить логику создания элементов вкладки, включая параметры назначения, в ActionFilter. Это позволяет мне повторно использовать логику создания вкладок для разных действий и контроллеров. Любое представление, содержащее частичный элемент управления вкладкой, получает атрибут CreatTabAttribute для соответствующего действия или контроллера, и его можно использовать.

Это может быть больше, чем вам нужно, но я надеюсь, что это поможет.

РЕДАКТИРОВАТЬ: Просто понял, что я не включил, как это выглядит в частичном представлении. На самом деле у меня есть расширение HtmlHelper, которое отображает более сложную вкладку, но вы поняли идею.

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<div id="tabs">
<%  
    if (null != ViewData.TabListGet()) {
        foreach(var item in ViewData.TabListGet()) {
%>
    <%= Html.ActionLink(item.Name, item.Action, item.Controller, item.RouteValues, null)%>
<%      
        }
    }
%>
</div>

РЕДАКТИРОВАТЬ: Добавление краткого примера ActionFilter я использую.

public class CreateContentTabsAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var result = filterContext.Result as ViewResultBase;
        if (null == result) return;

        var routeValues = filterContext.RouteData.Values;
        var repository = ObjectFactory.GetInstance<ITabRepository>();
        var context = filterContext.HttpContext;
        var userName = context.User.Identity.Name; // Or get id from Membership.
        var tabs = repository.ReadByUserId(userName);  

        TabItemDisplay defaultTab = null;
        var tabItems = new List<TabItemDisplay>();
        foreach (var tab in tabs)
        {
            var tabItem = new TabItemDisplay 
            { 
                Name = tab.Name,
                Action = "View",
                Controller = "Tab",
                RouteValues = new { key = tab.Key }
            };
            tabItems.Add(tabItem);
        }

        if (context.Request.IsAuthenticated)
        {
            tabItems.Add(new TabItemDisplay
            {
                Name = "Account",
                Action = "ChangePassword",
                Controller = "Account",
                RouteValues = new { siteKey = site.Key }
            });
        }

        result.ViewData.TabListSet(tabItems);
    }
}

Это только базовый пример извлечения вкладок из репозитория (создается с использованием StructureMap) и простой проверки, чтобы проверить, прошел ли пользователь аутентификацию. Но вы можете делать другие вещи, такие как получение запрошенного идентификатора пользователя для отображаемого пользователя из routeValues.

0 голосов
/ 12 октября 2010

Одним из решений является создание базового контроллера и наследование всех его контроллеров. в базовом контроллере вы можете добавить необходимое значение в viewmodel

public applicationController:Controller
{
   ViewData["linkvals"] = someValues;
}

public HomeContorller:ApplicationController{}

Второе решение - создать базовую модель представления и наследовать ее от всех моделей представления. в конструкторе базовой видовой модели вы можете создавать значения ссылок и присваивать им свойства

public baseViewModel
{
   public LinkVal{get;set;}
   public baseViewModel()
   {
      //calculate link vals
   }
}

public ViewModelA:baseViewModel{}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...