MVC - 将其他信息传递给视图

时间:2011-02-04 13:06:37

标签: c# asp.net-mvc asp.net-mvc-2

我正在使用Asp.Net MVC框架开发一个网站。我们需要在多个页面中添加一般用户信息,方式与堆栈溢出顶部的信誉栏类似。

我认为重要的是,为了将这些额外信息添加到视图中,不应该为创建控制器方法添加任何开销。这排除了在ViewData对象中传递此信息或修改ViewModel以接受信誉字段的选项,因为它会导致每个控制器看起来像这样:

public ActionResult Index()
{
    ViewData["reputationScore"] = GetUsersReputation(userId);

    // main controller logic here
}

如果在网站的90%页面上使用它,如果我们还想显示用户徽章计数,则更改可能非常耗时。

我可以想到4个解决方案

使用母版页 在后面的母版页代码中检索用户信誉,并在母版页标记中标记信誉。

缺点:

  1. 这似乎正在远离MVC所代表的一切。
  2. 我一直在寻求使用替代视图引擎(例如剃须刀)我不确定它们会如何混合。
  3. 它倾向于限制声誉的布局 - 很难将其放在页面中间。
  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隐喻,但有点麻烦。

    1. 是否有其他人提出了更好的解决方案
    2. 哪个最好 - 如果您使用过它们是否有效/有问题?

5 个答案:

答案 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方式,但它会起作用。