更好的方法来生成全局ViewData?

时间:2010-12-12 16:20:53

标签: c# asp.net-mvc

我的网站部分需要导航下拉列表的全局数据,现在我在属性中执行以下操作:

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
<% } %>

这样可行,但无论如何都要以更强类型的方式执行此操作?我唯一能想到的是使用ProjectNav作为成员创建一个Dto,但是你为每个控制器方法创建了一个单独的Dto,这绝对不是DRY。有没有更好的方法来解决这个问题,我只是错过了?

5 个答案:

答案 0 :(得分:2)

拥有NavigationController,并在每个视图(或母版页)中使用RenderAction或RenderPartial。

答案 1 :(得分:1)

创建一个基础ViewModel类,其上包含Projects属性。

在ActionFilter中创建OnResultExecuted方法。在OnResultExecuted方法中访问模型(filterContext.Controller.ViewData.Model)。检查它是否来自您的基本ViewModel类。如果是,请将其投射并将项目数据添加到其中。

现在,您在视图模型上有一个强类型的Projects属性,并使用ActionFilter进行设置。

或者,您也可以使用界面而不需要单个基础ViewModel类... if (model is IDisplayProjects) ...

答案 2 :(得分:0)

全球导航数据下降,这意味着它是页眉或页脚的一部分吗?我的方法是更喜欢声明它并将其加载到母版页中,或者更多的代码,放入具有特定功能的每个Controller的构造函数中。

答案 3 :(得分:0)

我会将模型放入Session并在用户首次登录时初始化该会话属性。或者如果没有登录,则在实际页面上初始化它。如果您的全局数据表示每个页面,则将其放在母版页中。

在母版页中这样的东西(GetProjects是一个静态函数):

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

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

这不是最强类型的方法,但非常简单有效。因此,通过这种方式,您无需在控制器级别担心它。

答案 4 :(得分: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帮助程序包含您需要的操作。