带有Initialize()的ASP.NET MVC Base Controller使用HTml.Action()多次执行

use*_*707 0 c# asp.net asp.net-mvc asp.net-mvc-4

这是关于ASP.NET MVC中的最佳实践的问题

我在MVC中创建了一个网站.因为每个页面都有一个菜单,我想我会创建一个基本控制器类,项目中的所有MVC控制器都继承该类.在基本控制器类的Initialize()函数中,我将加载我的菜单.通过这种方式,我可以保留我在一个地方加载菜单的逻辑并让它自动执行.

代码(C#):

public abstract class BaseController : System.Web.Mvc.Controller
{
    protected override void Initialize(System.Web.Routing.RequestContext requestContext)
    {
        //Load the menu:
        ViewBag.HeaderModel = LoadMenu();
    }
}

public class HomeController : BaseController
{
    public ActionResult Index()
    {
        //the menu is loaded by the base controller, so we can just return the view here
        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

这就像一个魅力.现在这是问题所在.

在我看来,我在网站上列出了五篇最新文章.由于文章在网站上有自己的逻辑和自己的部分,我创建了一个ArticleController,它继承自BaseController,其动作显示了我最近的五篇文章的PartialResult.

public class ArticlesController : BaseController
{
    public ActionResult DisplayLatestArticles()
    {
       var model = ... //abbreviated, this loads the latest articles
       return PartialView("LatestArticles", model);
    }
}
Run Code Online (Sandbox Code Playgroud)

并且在View中调用此方法:

@Html.Action("Index", new { controller = "Articles" })
Run Code Online (Sandbox Code Playgroud)

但这有一个缺点:即我的基本控制器上的Initialize()函数执行两次,这会将菜单加载两次,这是不合需要的(出于性能原因).到目前为止,我还没有找到避免这种行为的方法.

到目前为止,您对重构此代码有什么建议?我想确保加载我的菜单的逻辑停留在某处,以便自动调用它,而我或项目中的任何其他开发人员都不必担心它.我更喜欢保持我的逻辑以显示ArticlesController中的最新文章,因此与文章有关的一切都保存在自己的Controller中.

那么,如何最好地进行?

dav*_*v_i 5

您尝试做的更适合从_Layout.cshtml页面调用标题菜单.

_Layout.cshtml:

<html>
...
  <body>
...
    @Html.Action("Header", "SharedStuff")
...
Run Code Online (Sandbox Code Playgroud)

SharedStuffController.cs

public ActionResult Header()
{
    // logic to create header, also create a view
    return this.View();
}
Run Code Online (Sandbox Code Playgroud)

我觉得,基本控制器通常是错误的方法.上面的意思是你保持标题的所有逻辑很好地包含在描述它的东西中.