в asp.net-mvc, как лучше всего использовать Base ViewModel для отображения динамического контента на странице Site.Master

У меня есть сайт asp.net-mvc, и есть некоторая информация, которую я хочу показывать на каждой странице. Я создал класс BaseViewModel, и каждый из классов viewModel наследуется от BaseViewModel. Представление Site.Master напрямую связывается с BaseViewModel.

Прямо сейчас базовый класс имеет одно свойство под названием MenuLinks.

Свойство menulinks заполняется из вызова базы данных, поэтому при каждом действии контроллера, которое создает ViewModel, я добавляю новую строку:

 viewModel.MenuLinks = _repository.GetMenuLinks();

у меня много контроллеров, действий и моделей просмотра. Есть ли более чистый способ сделать это без необходимости помещать эту строку выше в каждое действие контроллера.


person leora    schedule 06.11.2010    source источник
comment
возможный дубликат Как использовать Base ViewModel в Asp.net MVC 2 - Dupe - это второй связанный вопрос, когда вы задали этот вопрос.   -  person John Farrell    schedule 07.11.2010


Ответы (5)


Вы можете написать собственный атрибут фильтра действия, который будет выполняться после каждого действия и устанавливать свойство базовой модели:

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

Теперь осталось украсить ваш базовый контроллер этим фильтром действий.

Другой способ справиться с этим — использовать дочерние действия и не имеют базовой модели представления.

person Darin Dimitrov    schedule 06.11.2010
comment
Сочинение › Наследство. Я делаю то же самое, но с ViewData[]. (Но только для главной страницы, в противном случае она будет включена в модель.) - person Ryan; 07.11.2010
comment
@Дарин в 2015 году, какой подход из двух, которые вы упомянули, вам больше всего нравится использовать? Спасибо - person Haroon; 01.05.2015

на странице site.master позвоните

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

вы можете вызвать действие в своем домашнем контроллере, если хотите, и просто вернуть частичное представление 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 %>
<% }%> 
person Justin Soliz    schedule 06.11.2010

Мне нравится пример Джастина, потому что он использует подход MVC. Я изменил его, чтобы он работал для MVC3 с бритвой. Вот что у меня есть в моем _Layout.cshtml:

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

Я создал 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
person Gluip    schedule 11.06.2011

Я думаю, что лучший способ добиться результата без изменения всех действий вашего контроллера — это создать настраиваемый фильтр действий, который заполняет свойство вашей BaseModel ссылками меню.

Затем вы могли бы иметь класс BaseController и добавить атрибут в BaseController.

person Lorenzo    schedule 07.11.2010

Создайте фабричный класс, который предоставит вам уже настроенную модель представления.

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();
person Marco Staffoli    schedule 07.11.2010