如何将模型加载到 _Layout.cshtml 并在各个视图之间共享?

5
我有一个MVC4项目,涉及“课程”。应用程序中的许多页面都需要处理课程列表 - 用户配置文件需要拉取列表,/Courses的Index视图需要拉取列表等。
由于这些数据几乎总是必需的,因此我希望将其作为初始请求的一部分加载,以便只查询一次数据库。
我想象一种情况,其中数据被放置在Layout.cshtml中,然后其他视图可以根据需要访问Model数据,尽管我没有看到清晰的实现方式。我认为我可以将问题分成两个部分:
1. 将数据加载到Layout.cshtml中 2. 从其他视图访问这些数据
我在两个方面都有些困惑 - 如何使其工作?

看一下这个 https://dev59.com/mm025IYBdhLWcg3wqX1o - Alex Art.
@AlexAr 那不是一回事。 - RobVious
"所以我只需要查询一次数据库" -- 每个请求都是完全独立的,所以无论你做什么,查询都会每次运行。当然,例外情况是如果您实现了某种形式的缓存;但重点在于,仅仅在比单个操作更高的级别上运行查询,并不能使其在不再次运行查询的情况下对所有其他操作可用。 - Chris Pratt
@Chris - 我的意思是针对课程只加载一次。随后的调用将是为其他数据 - 课程仅在每个会话中加载一次。这样清楚吗? - RobVious
这就是我所说的。除非你使用memcache或其他方式显式地缓存查询结果,并从该缓存中加载后续请求,而不是向数据库发出查询,否则每次都会进行查询,即使它在global.asax级别上完成了所有操作——每个请求都是唯一的,与上一个请求没有任何共享。 - Chris Pratt
3个回答

7
你应该使用CacheOutputCache,将这个列表放入一个Partial View中,然后在需要的地方进行渲染:
1)创建一个Action来填充Partial View。该视图将被缓存最长时间,然后任何访问都不会产生任何额外开销:
[NonAction]
[OutputCache(Duration = int.MaxValue, VaryByParam = "none")]
public ActionResult GetCourses()
{
  List<Course> courses = new List<Course>();

  /*Read DB here and populate the list*/

  return PartialView("_Courses", courses);
}

2) 使用 Chache 以相同的方式填充 Partial View:

[NonAction]
public ActionResult GetCourses()
{
  List<Course> courses = new List<Course>();

  if (this.HttpContext.Cache["courses"] == null)
  {
    /*Read DB here and populate the list*/

    this.HttpContext.Cache["courses"] = courses;
  }
  else
  {
    courses = (List<Course>)this.HttpContext.Cache["courses"];
  }

  return PartialView("_Courses", courses);
}

3)通过 Html.ActionHtml.RenderAction 渲染此视图:

@Html.Action("GetCourses", "ControllerName")

或者

@{ Html.RenderAction("GetCourses", "ControllerName"); }

有关缓存的更多信息:使用输出缓存提高性能


谢谢Fals,我会试一下。您可以给我展示一下_Courses局部视图的样子吗? - RobVious
如果你只需要课程列表,使用(2),并在视图中按照你的喜好呈现它!你可以访问this.HttpContext.Cache["courses"],或者将其引用到ViewBag或ViewData中,然后迭代生成任何你需要的HTML,无论你在哪里需要!我只是提供了一个缓存的想法! - Fals
我问这个问题的原因是我正在尝试从多个视图访问此数据 - 不一定是部分视图。我应该将此部分放在Layout.cshtml中吗?如果是这样,其他视图如何访问数据? - RobVious
1
还是你的意思是我应该为需要数据的每个视图拥有不同的部分视图,每个从缓存中加载?这对我来说很有道理...再次感谢你的耐心。 - RobVious

1
我有两个答案,因为我不确定我理解你的意愿。
1)创建静态帮助方法:
public static class Helper
{
  public static List<Course> GetCourses()
   {
    return db.Courses.ToList();
    }

}

然后你可以在视图或布局中随处调用它:

@Helper.GetCourses()

2) 我不喜欢在 ViewsLayout 中渲染业务逻辑。我会创建一个 BaseController,在这个控制器中获取 List<Course>。其他控制器应该继承自 BaseController。因此,在任何控制器的方法中,您都可以拥有相同的 List<Course> 实例。


0

将课程存储在HttpContext.Current.Items中,这将缓存该请求的项目,非常适合您的情况。 或者使用一些第三方缓存组件,如memcache。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接