Куда поместить логику для общих элементов (например, меню) с помощью MVC3?

#c# #asp.net-mvc-3 #model-view-controller #coding-style

#c# #asp.net-mvc-3 #модель-представление-контроллер #стиль кодирования

Вопрос:

После того, как я нашел это в нашем коде, я понял несколько вещей:

  • «сделай это сейчас, исправь позже» имеет ограничение
  • На самом деле я не знаю, куда это идет с MVC3
     @model int
    @using Company.Core.Logic.Financial
    @using Company.Core.Repositories
    @{
         var values = from AccountPlan e in new AccountPlanRepository().GetItemList()
                      where String.IsNullOrEmpty(e.PromoCode) // filter out promotional plans
                      select new { id = e.AccountPlanId, name = e.Description };
         var items = new SelectList(values, "id", "name", Model);
     }
    
    @Html.DropDownListFor(m => m, items)
     

В частности, это шаблон редактора ( @Html.EditorFor(m => m.AccountPlan) ), но это заставило меня понять, что я не знаю, где этот код используется для обычных вещей, таких как конструкторы меню. Если вы используете макеты для MVC3 (а кто нет), где код для построения меню сверху на основе ролей пользователя? Я бы предположил, что код представления будет перебирать готовые пункты меню и изменять их в HTML, но поскольку модель строго типизирована, означает ли это, что все модели должны знать о пунктах меню?

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

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

редактирование 2: В конечном итоге я хочу иметь чистое, возможно, даже зависимостно-инъекционное место для запуска кода, который вызывается из EditorTemplate . Возможно, это тот случай, когда EditorTemplate немедленно вызывает RenderAction?

Ответ №1:

Похоже, это довольно хорошо решает проблему (см. Отмеченный ответ, а не исходный вопрос):

http://forums.asp.net/t/1566328.aspx/1?Building ASP NET MVC Master Page Menu Dynamically Based on the current User s Role s quot

В принципе, вызовите RenderAction(...) , и он построит нужную модель, а не заставит вас требовать, чтобы для каждой модели требовался список пунктов меню.

Комментарии:

1. это кажется разумной идеей.

2. RenderAction решит мою проблему, если я смогу заставить шаблоны редактора вести себя так же.

Ответ №2:

Лично для меня я часто фильтрую меню на основе групп Active Directory, поэтому мне нужно знать, каковы их уровни доступа во всем приложении.

Я создаю новый контроллер, который я называю ControllerBase

 public class ControllerBase : Controller
{
    //authorization group setting an menu creation here.
    //set properties and objects to ViewBag items to access from the front end.

    protected override void Dispose(bool disposing)
    {
        _db.Dispose();
        base.Dispose(disposing);
    }
}
 

а затем на всех других контроллерах в моем проекте я просто расширяю из ControllerBase

 public class HomeController : ControllerBase
{}
 

Это сохраняет всю логику моего сервера в одном файле для управления разрешениями и предоставляет всем моим страницам доступ к этим переменным, когда мне нужно скрыть или показать разные элементы пользовательского интерфейса на основе разрешений.

Ответ №3:

Дочерние действия идеально подходят для этого сценария. Логика, необходимая для создания представления, заключена в действие контроллера, как обычно, и представление, которое хочет использовать дочернее действие, просто отображает действие..

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

например

 [OutputCache(Duration = 300)]
[ChildActionOnly]
public ViewResult MainMenu()
{
    var model = GetMenuModel();
    return View(model);
}
 

Представление, которое хочет отобразить дочернее действие, делает это следующим образом.

  @{ Html.RenderAction("MainMenu", "Account"); }
 

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

Существуют также перегрузки при визуализации, если ваше дочернее действие потребует от вас передачи ему параметров.

Комментарии:

1. По сути, так я обрабатываю свое главное меню и несколько других блоков HTML-кода типа «виджет», отображаемых в разных представлениях. Этот шаблон работает хорошо.

Ответ №4:

Вы не должны (должны) обращаться к репозиторию внутри представления. Это относится к контроллеру.

И меню реализовано на главной странице, вы не даете много подробностей о специфике.

Комментарии:

1. я не думаю, что это действительно отвечает на вопрос. он запрашивает рекомендации о том, как получать и передавать глобальные данные в _layout или какой-либо другой объект, не относящийся к представлению.

2. (Начало) вопроса не соответствует названию. Существует некоторый код Linq для заполнения выпадающего списка вопросом «куда это ведет».

3. Не уверен, почему вы проголосовали против, так что ставьте 1. Я хорошо знаю, что я (ну, я этого не писал …) не должен обращаться к репозиториям или, если на то пошло, создавать что-либо в представлении. Я обновлю свой вопрос, чтобы сделать это немного более очевидным.