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

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

главной страницы.

Вопрос

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

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

Фрагмент кода модели MasterPage View

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>.

Ответы [ 2 ]

17 голосов
/ 20 апреля 2009

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

Атрибут фильтра действий получает контроллер 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;
}
6 голосов
/ 27 апреля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...