in asp.net-mvc, what is the best way to have a Base ViewModel to show dynamic content on the Site.Master page

会有一股神秘感。 提交于 2019-12-02 05:23:14

问题


i have an asp.net-mvc site and there is some information that i want to show on every page. I have created a class called BaseViewModel and each of the viewModel classes inherit from BaseViewModel. The Site.Master view binds to the BaseViewModel directly.

Right now the base class has one property called MenuLinks.

The menulinks property gets populated from a database call so on every controller action that is instatiating a ViewModel i am adding a new line:

 viewModel.MenuLinks = _repository.GetMenuLinks();

i have a lot of controllers, actions and view models. Is there any cleaner way i can do the above without having to put this line above on every single controller action.


回答1:


You could write a custom action filter attribute which will execute after each action and set the property of the base model:

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();
        }
    }
}

Now all that's left is to decorate your base controller with this action filter.

Another way to handle this is to use child actions and not have a base view model.




回答2:


in your site.master page, call

<div id="menu-link">
  <% Html.RenderAction("Action", "Controller"); %>
</div>

you can call an action in your homecontroller if you want and just have it return a partial view of the html, in your case some menu links.

public class HomeController: Controller
{
    public ViewResult Menu() {
        var viewModel = new ViewModel();
        viewModel.MenuLinks = _repository.GetMenuLinks();

        return PartialView("MenuPartial", viewModel);
    }
}

you can create a partial "MenuPartial.ascx"

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



回答3:


I like justins example because it uses a MVC approach. I modified it so it works for MVC3 with razor. Here's what I have in my _Layout.cshtml:

        <div id="menucontainer">
            <ul id="menu">
                @Html.Action("Menu","Layout")
            </ul>
        </div>

I created a LayoutController that has a menu action like this:

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

        return PartialView(viewModel);
    }
}

Which renders a partial view name Menu.cshtml

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



回答4:


I think the best way to achieve your result without modifying all your controller action is to create a custom action filter that populate a property of your BaseModel with your menu links.

Then you could have a BaseController class and add the attribute to the BaseController.




回答5:


Create a factory class that give you the viewmodel already configured.

Class Factory{

  Repository _repository;

  public Factory(Repository repository){
    _repository = repository;
  }

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

}

then in your controller you can use the Factory class instead of directly create an instance of viewModel

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


来源:https://stackoverflow.com/questions/4115749/in-asp-net-mvc-what-is-the-best-way-to-have-a-base-viewmodel-to-show-dynamic-co

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!