2011-11-23 32 views
6

Al menos, creo que está relacionado con el problema. Mi caso es este:Editor Para no está trabajando en el tipo derivado

Tengo varias entidades comerciales con campos comunes, y cada una tiene campos personalizados únicos para esa entidad. Así que en el código, esto se modela como una clase EntityBase, y hay una serie de clases derivadas de esto, por ejemplo, Derived.

Para realizar una interfaz de usuario reutilizables, tengo una vista llamada EntityBase.vbhtml que tiene este aspecto:

@ModelType EntityBase 

@Using Html.BeginForm("Edit", Model.GetType.Name) 
    @* show the editor template for the derived type *@ 
    @* !!the next line renders nothing!! *@ 
    @Html.EditorFor(Function(x) Model, Model.GetType.Name) 

    [show a bunch of stuff common to all EntityBase objects] 
End Using 

y luego uno llamado Derived.vbhtml para las clases derivadas que hace esto:

@ModelType Derived 
[show an EditorFor for various Derived-specific fields] 

Luego, cuando navegue a \Derived\Edit\123, devuelve la vista predeterminada Derived\Edit.vbhtml, que simplemente hace esto:

@Html.EditorForModel("EntityBase") 

De esta manera, los controladores simplemente devuelven la vista de edición predeterminada esperada, que es una llamada de una sola línea a la vista EntityBase, que hace lo suyo e invoca el Derived para representar la clase derivada que no conoce.

Pensé que esto no tenía nada de especial, pero no funciona. Tal como está marcado en el código de vista, cuando llamo a EditorForModel dentro de la vista de clase base, especificando el nombre de la clase derivada para usar como una plantilla, no representa nada. He probado que si llamo a esta misma línea de código exacta en la plantilla Editar nivel superior, funciona bien. Entonces, hay algo acerca de la herencia que a MVC no le gusta, pero no puedo ver qué. ¡Por favor ayuda!

actualización: Funciona como yo esperaría si en lugar de EditorFor utilizo Partial (y mover la plantilla correspondiente a la carpeta compartida desde la carpeta EditorTemplates), pero eso no es una gran solución, porque creo que es confuso no siga la convención de nomenclatura para las plantillas EditorFor.

Respuesta

3

Parece que, aunque MVC no ubicará la plantilla con nombre en esta circunstancia, la encontrará si especifica la ruta completa a la plantilla. Así, en lugar de luchar contra esta más lejos, he implementado la siguiente función auxiliar:

<Extension()> _ 
Public Function EditorForObject(Of T, TValue)(ByVal htmlHelper As HtmlHelper(Of T), ByVal obj As TValue) As IHtmlString 
    Dim sTemplateName = "~/Views/Shared/EditorTemplates/" & obj.GetType.Name & ".vbhtml" 

    'Return htmlHelper.EditorFor(Function(x) obj) <-- this should work but doesn't 
    Return htmlHelper.Partial(sTemplateName, obj) 
End Function 

En Inglés, esto significa: pedir al objeto por su nombre de tipo, forman la ruta explícita al editor de plantillas de ese tipo, y luego invoque HtmlHelper.Partial, especificando el objeto y la ruta completa a la plantilla. Estoy seguro de que esto podría ser más general (y no codificado para vb), pero funciona.

A continuación, el uso es como esto:

@Html.EditorForObject(Model) 

y, de hecho, esto es incluso mejor que lo que yo estaba tratando de hacer, que es mucho más desordenado:

@Html.EditorFor(Function(x) Model, Model.GetType.Name) 

Incluso sin la consulta de plantilla problema, esto sería útil, porque es conveniente poder pasar un objeto para edición (o visualización), en lugar de un lambda ficticio que simplemente devuelve ese objeto.

Aún así, creo que el problema de búsqueda debe ser un error en MVC. (Si alguna vez tengo tiempo, creo que puedo verificar el código fuente.) ¿Alguien puede confirmar o comentar sobre esto?

+0

Tuve el mismo problema. Gracias por una gran solución. Estaba a punto de darme por vencido :) –

+0

¡Me alegra oírlo! Realmente me arranqué el pelo en esta. –

Cuestiones relacionadas