DisplayForModel具有视图名称参数错误

本文关键字:参数 错误 视图 DisplayForModel | 更新日期: 2023-09-27 18:19:54

我的显示模板"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.chtml重命名为MyPlan.chtml并使用

@Html.DisplayForModel()

一切都很好。你能帮我理解为什么会发生这种事吗?

谢谢!

编辑:

如果我完全按照上面描述的那样,显示模板文件名与视图模型名匹配,但我将视图名("MyPlan")传递给DisplayForModel,它仍然会抛出异常!!调用不带参数的DisplayForModel是可行的。这对我来说非常非常奇怪。几乎就像一个bug,但我确信这只是我不明白的事情。

DisplayForModel具有视图名称参数错误

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

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

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

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

找到与templateName匹配的视图,并将我的集合传递给它,并基于该视图生成html

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

这与使用[TemplateHint]属性时的工作原理相同,即它将模型传递给视图,因此如果模型是IEnumerable<T>,则视图也必须是@model IEnumerable<T>

因此,它是经过设计的(不是一个bug),它确实给了你很大的灵活性(例如,允许你为同一个模型使用多个模板),尽管行为可能没有得到应有的良好记录。

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

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

我还没有检查语法,但我觉得很正确。