2012-05-03 11 views
6

La aplicación es una aplicación MVC3 con motor de visualización RAZOR.¿Por qué RazorViewEngine no selecciona mi DisplayTemplate?

El controlador que se utiliza aquí es TestController. Estoy usando vistas anidadas.

Vista de la base (Listado de artículos) es la siguiente,

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

aquí es la plantilla para Punto

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

Y aquí es la vista de artículo Detalles

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

Así , Estoy intentando pasar el modelo de la plantilla ITEM a la plantilla ITEMDETAILS. ItemDetails.cshtml se coloca en "Vistas \ Prueba \ Plantillas de visualización". De hecho, he intentado colocarlo en las carpetas "Vistas \ Compartidas", así como "Vistas \ Compartidas \ Plantillas de visualización". Pero el motor View parece simplemente no recogerlo.

Sin embargo, la documentación de Microsoft here indica que el motor de vista se ve en la carpeta Controller \ DisplayTemplates para buscar el VIEW utilizando el TemplateName utilizado.

+1

Es probable que no sea un error. Por favor escriba un título más útil/relevante. –

+2

Tom, mi pregunta es por qué el motor de vista no está eligiendo la Vista. La pantalla para ItemDetails solo se muestra en blanco. Sin excepción. ¿Cómo puedo depurar cómo funciona el motor de vista detrás de escena? – EagerToLearn

+1

Nunca subestimes el poder de una buena siesta –

Respuesta

5

Este parece ser el comportamiento previsto para la visualización/EditorTemplates, presumiblemente para evitar que accidentalmente recursividad infinita en plantillas de pantalla personalizados, tales como hacer (en Item.cshtml):

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

. ..que mostraría infinitamente Item.cshtml DisplayTemplate.

Obviamente en su ejemplo está pasando el elemento/modelo a una plantilla diferente, por lo que no causaría una recursión infinita. Sin embargo, todavía parece quedar atrapado por la misma protección en el marco. ¿No está seguro de si se clasificaría como un "error" o simplemente "por diseño"?

Esta es la verificación en la 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 almacena los objetos/modelos visitados para las plantillas de los padres. Cuando se ejecuta:

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

Se hace su Item.cshtml DisplayTemplate y agrega el elemento/modelo para VisitedObjects.Esto significa que cuando Item.cshtml intenta mostrar otra plantilla niño con el mismo elemento/modelo:

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

El elemento/modelo ya está en VisitedObjects, por lo que la sentencia if anterior devuelve cierto y en lugar de hacer ItemDetails.cshtml vuelve simplemente en silencio/representa una cadena vacía

+0

Encontré esta "característica" recientemente y me causó consternación. Creo que el equipo de MVC cometió un error aquí. Devolver una cadena vacía le da al desarrollador la impresión de que todo fue bien, hasta que vean la salida. También hace que sea casi imposible saber qué está sucediendo. Por lo menos, el código podría lanzar una excepción, proporcionar una explicación del comportamiento y alertar al desarrollador sobre el problema. –

1

Primero, no use el bucle for. Display/EditorTemplates son capaces de manejar colecciones.

En segundo lugar, ¿qué es ItemsList? ¿Y cómo se define? Si solo está nombrando un tipo de colección particular, entonces no hagas eso. Solo tiene una Lista o algo más (a menos que necesite un manejo especial de elementos, en cuyo caso implemente IEnumerable en su clase de colección). A continuación, tendrá un ItemsList.cshtml o simplemente un Item.cshtml si lo convierte a una lista

Además, su DisplayFor() en la vista principal está mal. no puede pasar atributos html a DisplayTemplates de esa manera.

0

trate de usar @Html.RenderPartial("ItemDetails", item)

Cuestiones relacionadas