Подтвердить что ты не робот

Как создать строго типизированную главную страницу с использованием базового контроллера в ASP.NET MVC

Следуя примеру NerdDinners, я заинтересован в создании строго типизированной главной страницы. Для этого я использую базовый контроллер, который извлекает данные для главной страницы. Все остальные контроллеры наследуют этот класс. Аналогично, у меня есть ViewModels для главной страницы и любых других представлений. Класс ViewModel наследуется от главной страницы ViewModel.

Вопрос

Как должен дочерний контроллер убедиться, что данные главной страницы переданы в представление без установки свойств его ViewModel, относящихся к главной странице?

Моя главная страница отобразит несколько кнопок, которые определены в XML файле, и, следовательно, класс Buttons, который я заполняю.

Фрагмент кода ModelMage ViewModel

using System.Collections.Generic;

namespace Site1.Models
{
    public class MasterViewModel
    {
        public List<Button> Buttons{set; get;}
    }
}

Просмотр ViewModel

namespace Site1.Models
{
    public class View1ViewModel : MasterViewModel
    {
        public SomeDataClass SomeData { get; set; }
    }
}

Базовый контроллер

using System.Collections.Generic;
using System.Web.Mvc;
using Site1.Models;

namespace Site1.Controllers
{
    public abstract class BaseController : Controller
    {
        protected MasterViewModel model = new MasterViewModel();

        public BaseController()
        {
            model.Buttons = new List<Button>();
            //populate the button classes (doesn't matter how)
            PopulateButtons(model.Buttons);
        }
    }
}

Просмотр контроллера:

using System.Web.Mvc;

namespace Site1.Controllers
{
    public class View1Controller : BaseController
    {
        public ActionResult Index()
        {
            Models.View1ViewModel viewModel = new Models.View1ViewModel();
            SomeDataClass viewData = new SomeDataClass()
            //populate data class (doesn't matter how)
            PopulateDataClass(viewData);
            viewModel.SomeData = viewData;
            //I WANT TO ELIMINATE THE FOLLOWING LINE!
            viewModel.Buttons = model.Buttons;
            return View("Index", viewModel);
        }
    }
}

Основная страница наследует System.Web.Mvc.ViewMasterPage<Site1.Models.MasterViewModel>.

Представление наследует System.Web.Mvc.ViewMasterPage<Site1.Models.View1ViewModel>.

4b9b3361

Ответ 1

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

Атрибут фильтра действий получает контроллер ViewModel и передает его функции контроллера SetModel:

using System.Web.Mvc;
using Site1.Controllers;

namespace Site1.Models
{
    public class MasterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            base.OnActionExecuted(filterContext);

            MasterViewModel viewModel = (MasterViewModel)((ViewResultBase)filterContext.Result).ViewData.Model;

            BaseController controller = (BaseController)filterContext.Controller;
            controller.SetModel(viewModel);
        }
    }
}

Эта функция добавляется к BaseController:

public void SetModel(MasterViewModel childViewModel)
{
    childViewModel.Buttons = model.Buttons;
}

Ответ 2

Вместо того, чтобы создавать атрибут, почему бы не просто переопределить Controller.OnActionExecuted и поставить там код инициализации? Кажется немного проще.