在不违反MVC规则的情况下,如何将数据传递到母版页(使用ASP.NET MVC)?
就个人而言,我更喜欢对传递给所有视图的抽象控制器(基本控制器)或基类进行编码。
如果您希望视图具有强类型的视图数据类,则这可能对您有用。其他解决方案可能更正确,但这是设计和实用性恕我直言之间的良好平衡。
母版页采用强类型的视图数据类,该类仅包含与之相关的信息:
1 2 3 4
| public class MasterViewData
{
public ICollection<string> Navigation { get; set; }
} |
使用该母版页的每个视图都采用强类型化的视图数据类,该类包含其信息并从母版页视图数据派生:
1 2 3 4 5
| public class IndexViewData : MasterViewData
{
public string Name { get; set; }
public float Price { get; set; }
} |
由于我不希望各个控制器了解将母版页数据放在一起的任何信息,因此我将该逻辑封装到了一个传递给每个控制器的工厂中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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);
}
} |
继承与主视图之间的匹配关系很好,但是在渲染部分/用户控件时,我会将其视图数据组合到页面视图数据中,例如
1 2 3 4 5 6 7 8
| 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设计。
我更喜欢将主视图的数据驱动部分分解为多个部分,并使用Html.RenderAction进行渲染。与流行的视图模型继承方法相比,这具有几个明显的优点:
主视图数据与"常规"视图模型完全分离。这是继承而不是继承,导致了耦合更松散的系统,更易于更改。
主视图模型是通过完全独立的控制器操作建立的。"常规"操作无需为此担心,也不需要视图数据工厂,这对我来说似乎过于复杂。
如果您碰巧使用了AutoMapper之类的工具来将您的域映射到您的视图模型,您会发现配置起来更加容易,因为当您的视图模型不继承主视图数据时,它们将更像您的域模型。
使用针对主数据的单独操作方法,您可以轻松地将输出缓存应用于页面的某些区域。通常,主视图包含的数据更改频率少于主页内容。
编辑
通用错误在下面提供了更好的答案。请阅读!
原始答案
Microsoft实际上已经发布了处理此问题的"官方"方式的条目。这提供了逐步解释,并解释了其原因。
简而言之,他们建议使用抽象控制器类,但请亲自看看。
抽象控制器是一个好主意,但我还没有找到更好的方法。我也很想看看别人做了什么。
我做了一些研究,发现了这两个站点。也许他们可以提供帮助。
ASP.NET MVC技巧#31 –将数据传递到母版页和用户控件
使用ASP.NET MVC将数据传递到母版页
我发现,传递给视图的所有模型对象的公共父对象非常有用。
无论如何,页面之间总会有一些共同的模型属性。
其他解决方案缺乏优雅感,并且花费的时间太长。我为将近整整一整年做了一件非常可悲和贫穷的事情表示歉意:
1 2 3 4 5 6 7 8
| <script runat="server" type="text/C#">
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
MasterModel = SiteMasterViewData.Get(this.Context);
}
protected SiteMasterViewData MasterModel; |
因此,很明显,我在SiteMasterViewData上具有此静态方法Get(),该方法返回SiteMasterViewData。
我认为另一种好方法是为具有某些属性的视图(例如某些接口的ParentView)创建用于视图的接口,因此您可以将其用于需要引用页面的控件(父控件)和应从中访问的主视图意见。
Request.Params对象是可变的。在请求处理周期中向其添加标量值非常容易。从视图的角度来看,该信息可能已在QueryString或FORM POST中提供。高度