我是MVC的新手并决定将它用于我的最新项目。我的任务是为我的公司重新设计内部网主页,这实际上是列中的一堆链接和子链接。
示例:
他们希望这些链接来自一个数据库,该数据库将从/ admin页面进行管理(添加,编辑,排序,删除)。由于它是主页,我想尽可能少地进行db调用,但不一定是这样。
我创建了一个db表,在MVC中发现它很难(虽然我确实得到了它)迭代并在View页面中没有大量代码的情况下在页面上呈现它,我认为这不是目的/ MVC的最佳实践,我必须对我的模型做错事。
这是我的表结构,带有示例记录:
ID| Text | Href | OrderId | NewWindow | ParentId
1 | Head | NULL | 1 | 0 | NULL
2 | Link 1 | link1.htm | 1 | 1 | 1
3 | Link 2 | link2.htm | 2 | 1 | 1
4 | Link 3 | link3.htm | 2 | 1 | NULL
5 | Link 4 | link4.htm | 3 | 1 | NULL
6 | Link 5 | link5.htm | 1 | 1 | 5
我正在做这个非常混乱的foreach循环,返回整个表,我正在确定“头(父)链接”并相应地处理HTML。它真的让我想起了经典的asp时代。
我希望与模型有关并使用较小的数据集。
您对我应如何处理此事有任何提示/建议/意见吗?
答案 0 :(得分:0)
我在项目中做了同样的事情。如果此数据仅用于站点地图,那么数据库行就太麻烦了。
我使用了一个xml文件(也可以作为单个字段存储在db中)来保存站点地图,到目前为止工作正常。
这样做的好处是它可以很容易地绑定到分层小部件:tree或ul。并且易于缓存,因为它很少被修改。 链接和文本信息可以存储在xml属性中。
答案 1 :(得分:0)
正如您所说,最好避免在您的视图中使用这种复杂的逻辑。您应该尽可能地将视图简单数据传递给显示。你总是可能会有一些if
和foreach
语句,但是比你想要避免的更复杂。
最好在控制器中的操作方法中进行数据访问和对象的组装,而不是在视图中,通常甚至这些操作也可以用于某些其他服务(例如调用存储库,对mapper的调用。)一般来说,最好将ViewModel
个对象传递给视图,而不是直接从域中传递对象。 (虽然在这种情况下,因为对象总是用于显示目的,你可能不会太担心它。)
如果这些链接特定于主页,您可以将所有这些内容放在HomeController的动作方法中,或者如果它是站点范围的菜单,您可以使用单独的NavController来专门处理它。
e.g。
public class NavController : Controller
{
// ...
[ChildActionOnly]
public PartialViewResult SiteMenu(string currentPage)
{
// Get your flat list of menu items from the DB
var menuItems = _siteMapRepo.GetMenuItems();
// Map them into something more tree-like...
var treeMenu = MapFlatItemsToTreeMenu(menuItems);
return View("_Menu", treeMenu);
}
// ...
}
然后你可以有一个局部视图来呈现这些,例如_Menu.cshtml。
然后在父视图中的某个位置,很可能是您的网站布局,您可以通过RenderAction
来调用菜单:
@{Html.RenderAction("SiteMap", "Nav");}
_Menu.cshtml中的代码可能会变得有趣,因为您正在处理树结构。您可能在部分视图中具有递归调用,在叶节点处触底,此时最好使用RenderPartial而不是RenderAction,因为RenderAction会产生新请求。有点像...
@model MenuItem
@if (Model.HasChildren)
{
<ul>
@foreach (var child in Model.Children)
{
@{Html.RenderPartial("_Menu", child);}
}
</ul>
}
else
{
<li>
// do something with Model.Url etc.
</li>
}
免责声明:我实际上并没有尝试过,只是把它写出来,但它应该给我希望的要点。
您当然也可以查看其他人是否已经推出过您可以使用的内容,例如MvcSiteMapProvider或MvcTreeView。