如何使用ASP.NET MVC中的基本控制器创建强类型母版页

dar*_*asd 20 asp.net-mvc controller master-pages viewmodel

NerdDinners示例之后,我有兴趣创建一个强类型的母版页.为了实现这一点,我使用一个基本控制器来检索母版页的数据.所有其他控制器都继承此类.同样,我有ViewModels主页和任何其他视图.视图ViewModel类继承自母版页ViewModel.

子控制器应该如何确保将母版页的数据传递给View而不设置ViewModel与母版页本身相关的属性?

我的母版页将显示一些按钮,这些按钮在XML文件中确定,因此Buttons我填充的类.

MasterPage ViewModel代码段

using System.Collections.Generic;

namespace Site1.Models
{
    public class MasterViewModel
    {
        public List<Button> Buttons{set; get;}
    }
}
Run Code Online (Sandbox Code Playgroud)

视图 ViewModel

namespace Site1.Models
{
    public class View1ViewModel : MasterViewModel
    {
        public SomeDataClass SomeData { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

基础控制器

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

查看控制器:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

母版页继承System.Web.Mvc.ViewMasterPage<Site1.Models.MasterViewModel>.

视图继承System.Web.Mvc.ViewMasterPage<Site1.Models.View1ViewModel>.

Cra*_*ntz 17

您可以创建一个后执行执行的过滤器,该过滤器查找该类型的模型并相应地设置属性,可能通过调用基本控制器函数.然后,您可以将过滤器放在基类上,所有操作都会自动查看.

动作过滤器属性获取控制器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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

此功能添加到BaseController:

public void SetModel(MasterViewModel childViewModel)
{
    childViewModel.Buttons = model.Buttons;
}
Run Code Online (Sandbox Code Playgroud)

  • 在我尝试这个之前,对于一个非常常见的场景来说,这似乎是一个令人惊讶的复杂解决方案.或者人们不强烈输入他们的母版页? (2认同)
  • 谢谢你.最优秀.我需要在母版页上以不同的方式呈现一些东西,这个小窍门让我在那里. (2认同)

Mik*_*ike 6

而不是创建属性,为什么不覆盖Controller.OnActionExecuted并将初始化代码放在那里?看起来有点简单.