我正在使用Asp.Net MVC框架开发一个网站。我们需要在多个页面中添加一般用户信息,方式与堆栈溢出顶部的信誉栏类似。
我认为重要的是,为了将这些额外信息添加到视图中,不应该为创建控制器方法添加任何开销。这排除了在ViewData对象中传递此信息或修改ViewModel以接受信誉字段的选项,因为它会导致每个控制器看起来像这样:
public ActionResult Index()
{
ViewData["reputationScore"] = GetUsersReputation(userId);
// main controller logic here
}
如果在网站的90%页面上使用它,如果我们还想显示用户徽章计数,则更改可能非常耗时。
我可以想到4个解决方案
使用母版页 在后面的母版页代码中检索用户信誉,并在母版页标记中标记信誉。
缺点:
扩展HtmlHelper以添加GetUsersReputation方法 这似乎是对Html对象应该使用的内容的轻微违反 - 它不仅仅是渲染输出,而是命中数据库。除了违反这个比喻之外,我想不出任何其他重大问题。
覆盖System.Web.Mvc.ViewPage 重写Viewpage以暴露除Html之外的对象,该对象可用于调用访问数据库的一系列方法。确保可以使用与HtmlHelper相同的方式添加扩展方法,以便在需要新方法时,可以适当地扩展它。这可以让我们写出类似的东西:
<% DataAccess.GetUsersReputation() %>
创建基本通用视图模型 而不是将视图模型直接传递给视图,而是将其包装在可以包含所需方法的基本视图模型中:
public ActionResult Index()
{
MyViewModel viewCoreInfo = model.GetData();
return View(new BaseViewModel<MyViewModel>(viewCoreInfo));
}
BaseViewModel可以公开您需要的所有属性,以获取网页上所需的额外信息。例如UsersReputation(它可以在构造函数中查询数据库,也可以在访问属性时加载数据)。我认为这样可以更好地保持MVC隐喻,但有点麻烦。
答案 0 :(得分:3)
为什么不让MyViewModel
继承BaseViewModel
?
您可以使用BaseController.OnResultExecuting
填充常用值:
protected override void OnResultExecuting(ResultExecutingContext ctx) {
base.OnResultExecuting(ctx);
var baseView = ctx.Result as BaseViewModel;
if (baseView != null)
{
//assign values here
}
}
答案 1 :(得分:3)
既然你提到了转移到剃刀视图引擎的可能性,我认为ScottGu的THIS博客文章可能会引起人们的兴趣。
他讨论了使用剃刀使用“部分”,这将使您在布局(“母版页”)上创建一个可以添加内容的部分。以这种方式创建SO样式信息栏将简洁明了。
修改强>
根据以下评论渲染部分视图...新的mvc music store tutorial有一些例子。
在这种情况下,他们使用的是Html.RenderAction。 Html.RenderPartial是另一种选择。 这个差异在question中已经过时了,但我确定网上还有其他资源。
您的控制器只会返回部分视图:
return PartialView();
答案 2 :(得分:1)
您可以创建操作过滤器,覆盖OnResultExecuting,填充常用值并将其添加到您的操作/控制器中:
public class AddCommonData : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
ViewResult viewResult = filterContext.Result as ViewResult;
if (viewResult != null)
{
//...
}
}
}
答案 3 :(得分:0)
我已经完成了这项工作,我制作了一个基本模型类,其中包含所有共同的信息。我的所有其他viewmodel类都继承自这一个。但是你必须在每个控制器中填充这些信息。这是我选择的解决方案。
答案 4 :(得分:0)
您可以使用代码隐藏文件创建部分视图,您可以在其中使用数据填充部分视图。它有点非mvc方式,但它会起作用。