103

您在不违反 MVC 规则的情况下将数据传递到母版页(使用 ASP.NET MVC)的方式是什么?

就个人而言,我更喜欢编写抽象控制器(基本控制器)或传递给所有视图的基类。

4

9 回答 9

77

如果您希望您的视图具有强类型视图数据类,这可能对您有用。其他解决方案可能更正确,但恕我直言,这是设计和实用性之间的一个很好的平衡。

母版页采用强类型视图数据类,仅包含与其相关的信息:

public class MasterViewData
{
    public ICollection<string> Navigation { get; set; }
}

使用该母版页的每个视图都采用强类型视图数据类,其中包含其信息并派生自母版页视图数据:

public class IndexViewData : MasterViewData
{
    public string Name { get; set; }
    public float Price { get; set; }
}

由于我不希望各个控制器知道有关将母版页数据放在一起的任何信息,因此我将该逻辑封装到传递给每个控制器的工厂中:

public interface IViewDataFactory
{
    T Create<T>()
        where T : MasterViewData, new()
}

public class ProductController : Controller
{
    public ProductController(IViewDataFactory viewDataFactory)
    ...

    public ActionResult Index()
    {
        var viewData = viewDataFactory.Create<ProductViewData>();

        viewData.Name = "My product";
        viewData.Price = 9.95;

        return View("Index", viewData);
    }
}

继承很好地匹配主视图关系,但是在渲染部分/用户控件时,我会将他们的视图数据组合到页面视图数据中,例如

public class IndexViewData : MasterViewData
{
    public string Name { get; set; }
    public float Price { get; set; }
    public SubViewData SubViewData { get; set; }
}

<% Html.RenderPartial("Sub", Model.SubViewData); %>

这只是示例代码,并不打算按原样编译。专为 ASP.Net MVC 1.0 设计。

于 2009-04-14T01:33:07.737 回答
60

我更喜欢将主视图的数据驱动部分分解为部分并使用Html.RenderAction呈现它们。与流行的视图模型继承方法相比,这具有几个明显的优势:

  1. 主视图数据与“常规”视图模型完全分离。这是组合而不是继承,并导致更松散耦合的系统更容易更改。
  2. 主视图模型由完全独立的控制器操作构建。“常规”操作不需要担心这一点,也不需要视图数据工厂,这对我的口味来说似乎过于复杂。
  3. 如果您碰巧使用AutoMapper之类的工具将您的域映射到您的视图模型,您会发现配置起来更容易,因为当您的视图模型不继承主视图数据时,它们将更接近于您的域模型。
  4. 使用针对主数据的单独操作方法,您可以轻松地将输出缓存应用到页面的某些区域。通常,主视图包含的数据更改频率低于主页内容。
于 2010-08-09T21:48:08.820 回答
20

编辑

通用错误在下面提供了更好的答案。请阅读!

原始答案

微软实际上已经发布了一个关于“官方”方式来处理这个问题的条目。这提供了一步一步的演练,并解释了他们的推理。

简而言之,他们建议使用抽象控制器类,但请自行查看。

于 2009-06-04T06:26:58.863 回答
7

抽象控制器是个好主意,我还没有找到更好的方法。我也很想看看其他人做了什么。

于 2008-09-17T00:12:41.573 回答
3

我做了一些研究,发现了这两个网站。也许他们可以提供帮助。

ASP.NET MVC 技巧 #31 – 将数据传递给母版页和用户控件

使用 ASP.NET MVC 将数据传递到母版页

于 2008-09-17T00:15:18.527 回答
2

我发现传递给视图的所有模型对象的共同父对象非常有用。

无论如何,页面之间总会有一些共同的模型属性。

于 2008-09-17T00:27:34.657 回答
0

Request.Params 对象是可变的。作为请求处理周期的一部分,向其添加标量值非常容易。从视图的角度来看,该信息可能已在 QueryString 或 FORM POST 中提供。hth

于 2008-09-17T00:12:56.223 回答
0

我认为另一种好方法可能是使用某些属性(例如某些接口的 ParentView)为视图创建接口,因此您可以将它用于需要引用页面(父控件)的控件和应从其访问的主视图意见。

于 2008-09-17T00:19:25.740 回答
0

其他解决方案缺乏优雅且耗时太长。我为几乎整整一年后做了这件非常悲伤和贫困的事情而道歉:

<script runat="server" type="text/C#">
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        MasterModel = SiteMasterViewData.Get(this.Context);
    }

    protected SiteMasterViewData MasterModel;
</script>

很明显,我在 SiteMasterViewData 上有这个静态方法 Get(),它返回 SiteMasterViewData。

于 2009-09-30T05:28:38.703 回答