具有视图名称参数错误的DisplayForModel

时间:2013-06-25 15:43:34

标签: c# asp.net-mvc asp.net-mvc-4 razor invalidoperationexception

我的显示模板“PlanAlternate”:

@model MyPlan

<div class="span4 compare-column compare-column1">

<div class="compare-row-plan">
    <h3>@Model.Plan.Name</h3>
</div>

@foreach (var benefit in Model.Plan.Benefits)
{
    <div class="compare-row-benefit-description">
        @benefit.Description
    </div>
}

<div class="compare-row-submit">
    <input class="btn" type="submit" value="Apply Now" />
</div>
</div>

我的使用显示模板的视图:

@model IEnumerable<MyPlan>

<div class="span9 compare-data-wrapper">
   @Html.DisplayForModel("PlanAlternate")
</div>

这会引发异常:

传递到字典中的模型项的类型为'System.Collections.Generic.List`1 [MyPlan]',但此字典需要“MyPlan”类型的模型项。

但是,如果我将显示模板从PlanAlternate.cshtml重命名为MyPlan.cshtml并使用

@Html.DisplayForModel()

一切正常。你能帮我理解为什么会这样吗?

谢谢!

编辑:

如果我完全按照上面描述的那样显示模板文件名与视图模型名称匹配,但我将视图名称(“MyPlan”)传递给DisplayForModel,它仍会抛出异常!调用不带参数的DisplayForModel有效。这对我来说似乎非常非常奇怪。几乎像一个错误但我确定这只是我不理解的东西。

2 个答案:

答案 0 :(得分:3)

DisplayForModel()(和DisplayFor(m => m))方法在内部使用TemplateHelpers类中的internal static方法。代码非常复杂,我将留给您更详细地探索源代码,但总结一下会发生什么:

当你没有传递templateName值时,助手基本上会说

找到与我的模型名称相匹配的视图名称名称,并根据该视图为我的收藏中的每个项目生成html

但是当你传递templateName值时,助手基本上会说

找到我匹配templateName的视图并将我的集合传递给它并根据该视图生成html

会导致您的异常,因为它会将IEnumerable<MyPlan>的模型传递给期望模型为MyPlan的视图。

这与使用[TemplateHint]属性时相同 - 即它将模型传递给视图,因此模型为IEnumerable<T>,视图也必须为@model IEnumerable<T>

所以它是设计的(不是bug),它确实为你提供了很大的灵活性(例如,允许你为同一个模型提供多个模板),尽管这种行为可能没有记录得那么好

答案 1 :(得分:0)

您的模板需要单个MyPlan实例的模型,其中视图中包含MyPlan对象列表。因为您没有向DisplayForModel提供任何对象,所以它只是从视图中传递模型。要做你想做的事,你必须将一个DisplayForModel包装在for循环中,并在循环的每次迭代中从IEnumerable传递一个MyPlan实例,即

foreach(var myPlan in Model)
{
    @Html.DisplayForModel("PlanAlternate", myPlan)
}

我没有检查语法,但看起来对我来说。