我的网站部分需要导航下拉列表的全局数据,现在我在属性中执行以下操作:
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。有没有更好的方法来解决这个问题,我只是错过了?
答案 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
帮助程序包含您需要的操作。