为什么RazorViewEngine没有拿起我的DisplayTemplate?

时间:2012-05-03 20:36:29

标签: asp.net visual-studio-2010 asp.net-mvc-3 razor

Application是一个带有RAZOR视图引擎的MVC3应用程序。

这里使用的控制器是TestController。 我正在使用嵌套视图。

基本视图(项目列表)是这样的,

//Listing.cshtml
@model ItemsList 
@for (int i = 0; i < Model.Items.Count(); i++)
    {
        @Html.DisplayFor(x => x.Items[i], new { RowPosition = i})
}

这是Item

的模板
//Item.cshtml
@model Item
@Html.DisplayFor(x=>x.HeaderText)
@Html.DisplayFor(x=>x, "ItemDetails")

这是项目详细信息的视图

//ItemDetails.cshtml
@model Item
@Html.DisplayFor(x=>x.Description)

所以,我正在尝试将模型从ITEM模板传递到ITEMDETAILS模板。 ItemDetails.cshtml位于“Views \ Test \ DisplayTemplates”下。事实上我已经尝试将它放在文件夹“Views \ Shared”以及“Views \ Shared \ DisplayTemplates”下。但View引擎似乎不是要把它拿起来。

但Microsoft文档here表明视图引擎确实在Controller \ DisplayTemplates文件夹中查找使用TemplateName来获取VIEW。

3 个答案:

答案 0 :(得分:5)

这似乎是Display / EditorTemplates的预期行为,可能是为了防止在自定义显示模板中意外无限递归,例如执行(在Item.cshtml中):

@model Item
@Html.DisplayFor(x => x)

...它将无限地显示Item.cshtml DisplayTemplate。

显然,在您的示例中,您将项目/模型传递给不同的模板,因此不会导致无限递归。但是,它似乎仍然被框架中的同一个安全防范所抓住。不确定它是否会被归类为“错误”或仅仅是“设计”?

这是DisplayFor/TemplateFor helper

中的检查
// Normally this shouldn't happen, unless someone writes their own custom Object templates which 
// don't check to make sure that the object hasn't already been displayed 
object visitedObjectsKey = metadata.Model ?? metadata.RealModelType;
if (html.ViewDataContainer.ViewData.TemplateInfo.VisitedObjects.Contains(visitedObjectsKey)) {    // DDB #224750 
    return String.Empty;
}

ViewData.TemplateInfo.VisitedObjects存储父模板的访问对象/模型。当你跑:

@Html.DisplayFor(x => x.Items[i], new { RowPosition = i})

它呈现您的Item.cshtml DisplayTemplate,并将项目/模型添加到VisitedObjects。这意味着当Item.cshtml尝试显示具有相同项目/模型的另一个子模板时:

@Html.DisplayFor(x => x, "ItemDetails")

项目/模型已经在VisitedObjects中,因此上面的if语句返回true而不是呈现ItemDetails.cshtml它只是静默地返回/呈现一个空字符串。

答案 1 :(得分:1)

首先,不要使用for循环。 Display / EditorTemplates能够处理集合。

第二,什么是ItemsList?它是如何定义的?如果它只是命名一个特定的收集类型,那么不要这样做。只需要一个List或者其他东西(除非你需要特殊的项目处理,在这种情况下在你的集合类上实现IEnumerable)。如果转换为使用List

,则可以使用ItemsList.cshtml或只是Item.cshtml

另外,主视图中的DisplayFor()是错误的。你不能以这种方式将html属性传递给DisplayTemplates。

答案 2 :(得分:0)

尝试使用@Html.RenderPartial("ItemDetails", item)