我正在使用Asp.Net MVC框架开发网站。我们需要在一些页面上添加通用用户信息,类似于stack overflow顶部的声望栏。
我认为,在创建控制器方法时不应增加任何开销以将此额外信息添加到视图中。这排除了通过ViewData对象传递此信息的选项,或更改ViewModels以接受声誉字段的选项,因为这将导致每个控制器看起来都像这样:
如果在网站的90%页面上都使用了这个功能,那么想要显示用户徽章计数也将非常耗时,需要进行大量修改。
我能想到4种解决方案:
1、使用Master页面。 在Master页面代码后端中检索用户信誉度,并在Master页面标记中添加信誉度的标记。
缺点: - 这似乎偏离了MVC的所有特点。 - 我一直在考虑转向使用替代视图引擎(例如razor),我不确定它们能否很好地混合。 - 它往往会限制声望的布局 - 很难把它放在页面中间。
2、扩展HtmlHelper以添加GetUsersReputation方法。 这似乎是对Html对象使用的轻微违规——它不仅渲染输出,而且还会访问数据库。除此之外,我无法想到任何其他重大问题。
3、覆盖System.Web.Mvc.ViewPage。 重写Viewpage以公开一个对象,除Html外,该对象还可用于调用访问数据库的一系列方法。确保可以像添加HtmlHelper那样添加扩展方法,以便在需要新方法时可以适当地扩展它。这可能会使我们编写类似以下内容的内容:
4、使用部分类和扩展方法。 通过创建存储器实现与视图分离。在存储器中添加扩展方法以处理与数据库的交互。然后使用部分类将它们绑定到视图上。这种方法使视图保持简单,并使存储器具有最大灵活性。
我认为,在创建控制器方法时不应增加任何开销以将此额外信息添加到视图中。这排除了通过ViewData对象传递此信息的选项,或更改ViewModels以接受声誉字段的选项,因为这将导致每个控制器看起来都像这样:
public ActionResult Index()
{
ViewData["reputationScore"] = GetUsersReputation(userId);
// main controller logic here
}
如果在网站的90%页面上都使用了这个功能,那么想要显示用户徽章计数也将非常耗时,需要进行大量修改。
我能想到4种解决方案:
1、使用Master页面。 在Master页面代码后端中检索用户信誉度,并在Master页面标记中添加信誉度的标记。
缺点: - 这似乎偏离了MVC的所有特点。 - 我一直在考虑转向使用替代视图引擎(例如razor),我不确定它们能否很好地混合。 - 它往往会限制声望的布局 - 很难把它放在页面中间。
2、扩展HtmlHelper以添加GetUsersReputation方法。 这似乎是对Html对象使用的轻微违规——它不仅渲染输出,而且还会访问数据库。除此之外,我无法想到任何其他重大问题。
3、覆盖System.Web.Mvc.ViewPage。 重写Viewpage以公开一个对象,除Html外,该对象还可用于调用访问数据库的一系列方法。确保可以像添加HtmlHelper那样添加扩展方法,以便在需要新方法时可以适当地扩展它。这可能会使我们编写类似以下内容的内容:
4、使用部分类和扩展方法。 通过创建存储器实现与视图分离。在存储器中添加扩展方法以处理与数据库的交互。然后使用部分类将它们绑定到视图上。这种方法使视图保持简单,并使存储器具有最大灵活性。
<% DataAccess.GetUsersReputation() %>
创建一个基础通用视图模型 不要直接将视图模型传递给视图,而是将其包装在一个基础视图模型中,该模型可以保存所有所需的方法:
public ActionResult Index()
{
MyViewModel viewCoreInfo = model.GetData();
return View(new BaseViewModel<MyViewModel>(viewCoreInfo));
}
BaseViewModel可以公开您在网页上需要的所有属性,例如UsersReputation(它可以在构造函数中查询数据库,或在访问该属性时加载数据)。我认为这更好地维护了MVC隐喻,但有点繁琐。
- 是否有其他人提出了更好的解决方案?
- 哪个是最好的 - 如果您使用过它们,它们是否有效/存在问题?
IMasterPageData
的接口。让你的BaseViewModel
和FriendDataBaseViewModel
实现它。然后只需将OnResultExecuting
中的检查更改为IMasterPageData
即可。 - jgauffin