关于asp.net mvc:使用模型和ViewData项创建ViewDataDictionary的简写?

Shorthand for creating a ViewDataDictionary with both a model and ViewData items?

有没有办法用一个模型和一行代码的附加属性来创建一个ViewDataDictionary。我试图在组装模型和一些额外的显示配置属性时调用一个强类型视图,而不需要跨多行显式组装ViewDataDictionary。似乎在RenderPartial过载的情况下,可以同时采用objectViewDataDictionary两种型号,但当两种型号都被填充时,它似乎只是忽略了ViewDataDictionary

1
2
3
// FAIL: This will result in ViewData being a ViewDataDictionary
// where Model = MyModelObject and there are no other parameters available.
this.Html.RenderPartial("SomePartialView", MyModelObject, new ViewDataDictionary(new { SomeDisplayParameter = true }));

我发现其他人也有同样的问题,但他们的解决方案与我发现的多行概念是一样的:用模型创建一个离散的ViewDataDictionary,添加新参数并在RenderPartial调用中使用它。

1
2
3
var SomeViewData = new ViewDataDictionary(MyModelObject);
SomeViewData.Add("SomeDisplayParameter", true);
this.Html.RenderPartial("SomePartialView", SomeViewData);

我总是可以将该逻辑包装到一个ChainedAdd方法中,该方法返回一个添加了新元素的重复字典,但似乎我缺少了创建一个ViewDataDictionary的方法,它可以为我做到这一点(这比我希望的开销要多一些)。

2

同样,试图用显式的ModelModelState组装ViewDataDictionary只会导致编译错误,因为modelstate是只读的。

1
2
// FAIL: Compilation error
this.Html.RenderPartial("SomePartialView", new ViewDataDictionary { Model = MyModelObject, ModelState = new ViewDataDictionary( new { SomeDisplayParameter = true }});

答案:看起来Craig和我最终找到了两个独立的语法来完成这项工作。在这种情况下,我肯定有偏见,但我喜欢先设置模型,然后"装饰"模型的想法。

4

当然,如果他(最终)不回答我的话,我还是会转动我的轮子,所以圆就是正方形的。


使用对象初始值设定项和集合初始值设定项:

1
2
3
4
new ViewDataDictionary(new ViewDataDictionary() { {"SomeDisplayParameter", true }})
    {
        Model = MyModelObject
    }

内部viewdatadictionary初始化其集合,然后使用构造函数重载填充"real"viewdatadictionary,该构造函数重载使用viewdatadictionary而不是对象。最后,对象初始值设定项设置模型。

然后在不单独设置myModelObject的情况下传递整个过程:

1
2
3
this.Html.RenderPartial("SomePartialView", null,
    new ViewDataDictionary(new ViewDataDictionary() { {"SomeDisplayParameter", true }})
        { Model = MyModelObject });


以Craig的答案为起点——我甚至不知道你可以将构造函数调用和对象初始值设定项结合在一起——我偶然发现了巴勒莫的这段代码,它导致了一种有效的组合。他使用某种类型的字典速记法,当ViewDataDictionary对象初始值设定项使用时,以某种方式填充ModelState

2

我仍然看不到这是如何工作的,因为您不能在初始值设定项中显式地设置ModelState,但它似乎维护了视图的原始模型对象和"附加"参数。这种语法中肯定有许多其他排列不起作用——不能在单个对象中将模型与字典组合在一起,也不能为字典值使用对象初始值设定项语法——但上述版本似乎起作用。


我在htmlhelper上创建了一个扩展方法,将属性名和值从匿名对象复制到viewdatadictionary。

样品

1
Html.RenderPartial("SomePartialView", MyModelObject, new { SomeDisplayParameter = true })

HTMLHelper扩展

1
2
3
4
5
6
7
8
public static void RenderPartial(this HtmlHelper htmlHelper, string partialViewName, object model, object viewData)
{
    var vdd = new ViewDataDictionary(model);
    foreach (var property in viewData.GetType().GetProperties()) {
        vdd[property.Name] = property.GetValue(viewData);
    }
    htmlHelper.RenderPartial(partialViewName, vdd);
}


这就是我在旧式MVC ASPX视图中的工作原理:

1
<% Html.RenderPartial("ContactPartial", Model.ContactFactuur, new ViewDataDictionary(this.ViewData ) { TemplateInfo = new TemplateInfo { HtmlFieldPrefix ="Factuur" } }); %>

这里的内容是,在构造函数中,我使用当前的viewdata"new viewdatadictionary(this.viewdata)",它是一个包含我需要的用于validationMessages的ModelState的viewdatadictionary。


我带着同样的问题来到这里。

我想可能是这样的(请原谅vb razor语法)

1
 @Code Html.RenderPartial("Address", Model.MailingAddress, New ViewDataDictionary(New With {.AddressType ="Mailing Address"}))End Code

但当然,在运行时会出现此错误:

用户代码未处理System.InvalidOperationException

message=传递到字典中的模型项的类型为"vb$anonymousType_1`1[system.string]",但此字典需要"viewModel.address"类型的模型项。

但我发现,我真正想要使用的是编辑器模板。

代替渲染的部分用途:

4

编辑器模板只是一个局部视图

~/views/模型共享/editoremplates/templatename.vbhtml

我的地址模板是一个强类型的部分视图,但editorfor方法提供了使用anon对象轻松添加其他视图数据项的功能。

在上面的示例中,我不需要包括模板名"address",因为MVC将查找与模型类型同名的模板。

您也可以用同样的方法覆盖显示模板。