【问题标题】:How to create a strongly typed master page using a base controller in ASP.NET MVC如何使用 ASP.NET MVC 中的基本控制器创建强类型母版页
【发布时间】:2010-10-20 13:46:51
【问题描述】:

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

问题

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

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

MasterPage 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&lt;Site1.Models.MasterViewModel&gt;

视图继承System.Web.Mvc.ViewMasterPage&lt;Site1.Models.View1ViewModel&gt;

【问题讨论】:

  • 将无问题的解决方案移到它所属的已接受解决方案中。这清楚地分离了 Stack Overflow 使用的问题/答案模型。

标签: asp.net-mvc controller master-pages viewmodel


【解决方案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;
}

【讨论】:

  • 在我尝试这个之前,对于一个非常常见的场景来说,这似乎是一个非常复杂的解决方案。还是人们不强烈键入他们的母版页?
  • 我没有见过很多强类型的母版页。但是,您将遇到同样的问题,即必须使用 ViewDataDictionary 设置公共属性。然而,事实证明,创建一个动作过滤器真的非常简单。我认为你高估了并发症。
  • 啊,我看到你已经更新了这个问题的实现。很简单,不是吗!
  • 谢谢。最优秀的。我需要在母版页上以不同的方式呈现一些东西,这个技巧让我成功了。
【解决方案2】:

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

【讨论】:

  • 这是来自 MSDN 的考虑:“如果在派生的 Controller 类中重写此方法,则将为类中的每个操作方法调用它。为了更灵活,从 ActionFilterAttribute 派生一个类并重写它派生的 ActionFilterAttribute 类中的方法。"
  • Link to MSDN documentation for Controller.OnActionExecuted 包含上述评论中引用的 Aaron 引用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多