2010-12-12 4 views
3

У меня есть раздел моего сайта, который требует глобальных данных для падения навигации вниз, прямо сейчас я делаю следующее внутри атрибута:Лучший способ генерации глобальных ViewData?

ViewData["projects"] = new[] 
{ 
    new ProjectNav { Id = 1, Name = "Big project in New York" }, 
    new ProjectNav { Id = 2, Name = "Small project in New Jersey" }, 
    new ProjectNav { Id = 3, Name = "Big project in Florida" }, 
} 

Я тогда разметка моих методов контроллера, как это:

[ProjectNav] 
public ActionResult Index() 
{ 
    // strongly typed view returned here 
} 

И на мой взгляд, я хотел бы сделать что-то вроде этого:

<% foreach (ProjectNav project in (IEnumerable<ProjectNav>)ViewData["projects"]) 
{ %> 
// Enumerate here 
<% } %> 

Это работает, но есть в любом случае сделать это в большей степени типизированный путь? Единственное, о чем я могу думать, это создать Dto с материалом ProjectNav в качестве члена, но тогда вы создаете отдельное Dto для каждого из методов контроллера, и это определенно не СУХОЙ. Есть ли лучший способ сделать это, что я просто отсутствую?

ответ

2

Имейте NavigationController и используйте RenderAction или RenderPartial в каждом представлении (или на главной странице).

+0

+1, RenderAction - ваш друг в этой ситуации. – mxmissile

0

Глобальные данные для навигации выпадающие, что означает, что это часть верхнего или нижнего колонтитула справа? Мой подход предпочитает объявлять его и загружать на главную страницу или, более код, помещать в конструктор каждого контроллера определенную функцию.

0

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

Так что-то подобное в MasterPage (где GetProjects является статической функцией):

<% if(Session["projects"] == null) 
{ 
    Session["projects"] = DataManager.GetProjects(); 
}%> 

<% foreach (ProjectNav project in (IEnumerable<ProjectNav>)Session["projects"]) 
{ %> 
    // Enumerate here 
<% } %> 

Не самым сильно типизированным способ сделать это, но очень простой и эффективный. Таким образом, вам не нужно беспокоиться об этом на уровне контроллера.

1

Создайте базовый класс ViewModel с свойством Projects на нем.

Создайте метод OnResultExecuted в вашем ActionFilter. В методе OnResultExecuted доступ к модели (filterContext.Controller.ViewData.Model). Убедитесь, что он получен из базового класса ViewModel. Если это так, добавьте его и добавьте в него данные о проектах.

Теперь у вас есть строго типизированное свойство Projects на вашей модели просмотра, и оно устанавливается с помощью ActionFilter.

В качестве альтернативы вы также можете использовать интерфейс вместо того, чтобы требовать один базовый класс ViewModel ... if (model is IDisplayProjects) ....

+0

Я сделал это без проблем. –

0

Использование child actions - гораздо лучшее решение. Таким образом, вы бы начать с определения контроллера:

public class ProjectsController: Controller 
{ 
    public ActionResult Index() 
    { 
     var projects = new[] 
     { 
      new ProjectNav { Id = 1, Name = "Big project in New York" }, 
      new ProjectNav { Id = 2, Name = "Small project in New Jersey" }, 
      new ProjectNav { Id = 3, Name = "Big project in Florida" }, 
     }; 
     return View(projects); 
    } 
} 

А затем строго типизированный частичный, который будет оказывать им (~/Views/Projects/Index.ascx) и, наконец, включить это в главном окне:

<%= Html.Action("index", "projects") %> 

Таким образом, вы дон Не нужно украшать все действия вашего контроллера атрибутами. Просто включите действие, которое вам нужно, используя помощник Html.Action.

Смежные вопросы