在asp.net-mvc中,使用Base ViewModel在Site.Master页面上显示动态内容的最佳方法是什么

我有一个asp.net-mvc网站,我希望在每个页面上显示一些信息。 我创建了一个名为BaseViewModel的类,每个viewModel类都inheritance自BaseViewModel。 Site.Master视图直接绑定到BaseViewModel。

现在,基类有一个名为MenuLinks的属性。

menulinks属性从数据库调用填充,因此在每个控制器操作上,我正在添加一个新行:ViewModel:

viewModel.MenuLinks = _repository.GetMenuLinks(); 

我有很多控制器,动作和视图模型。 有没有更清洁的方法,我可以做到上述,而不必将这一行放在每一个控制器动作上面。

您可以编写一个自定义操作filter属性 ,该属性将在每个操作后执行并设置基本模型的属性:

 public override void OnActionExecuted(ActionExecutedContext filterContext) { base.OnActionExecuted(filterContext); var viewResult = filterContext.Result as ViewResultBase; if (viewResult != null) { var model = viewResult.ViewData.Model as BaseViewModel; if (model != null) { model.MenuLinks = _repository.GetMenuLinks(); } } } 

现在剩下的就是用这个动作filter来装饰你的基本控制器。

处理此问题的另一种方法是使用子操作而不是基本视图模型。

在您的site.master页面中,致电

  

如果你愿意,你可以在家庭控制器中调用一个动作,然后让它返回html的局部视图,在你的情况下是一些菜单链接。

 public class HomeController: Controller { public ViewResult Menu() { var viewModel = new ViewModel(); viewModel.MenuLinks = _repository.GetMenuLinks(); return PartialView("MenuPartial", viewModel); } } 

你可以创建一个部分“MenuPartial.ascx”

 <% foreach(var link in Model.MenuLinks) { %> <%: link.Name %> <% }%> 

我喜欢justins的例子,因为它使用了MVC方法。 我修改了它,因此适用于带razor的MVC3。 这是我在_Layout.cshtml中的内容:

   

我创建了一个LayoutController,其菜单操作如下:

 public class LayoutController : Controller { // // GET: /Layout/ public PartialViewResult Menu() { var viewModel = new MenuViewModel {IsAdministrator = true}; return PartialView(viewModel); } } 

其中呈现部分视图名称Menu.cshtml

 @model MenuViewModel @if (Model.IsAdministrator) { //render admin stuff } //render other items 

我认为在不修改所有控制器操作的情况下实现结果的最佳方法是创建一个自定义操作filter,使用菜单链接填充BaseModel的属性。

然后你可以有一个BaseController类并将该属性添加到BaseController。

创建一个工厂类 ,为您提供已配置的视图模型。

 Class Factory{ Repository _repository; public Factory(Repository repository){ _repository = repository; } public ViewModel GetViewModel(){ var viewModel = new ViewModel(); viewModel.MenuLinks = _repository.GetMenuLinks(); return viewModel; } } 

然后在您的控制器中,您可以使用Factory类,而不是直接创建viewModel的实例

  ... your controller ... var factory = new Factory(_repository); var viewMolde = factory.GetViewModel();