Некоторое время назад я написал сайт, где у меня были разные вкладки, которые переходили в разные места для разных пользователей. Я проведу вас через мое решение, надеюсь, я правильно понял вопрос, и это поможет.
Что касается получения данных в и из 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.