2011-11-23 38 views
6

至少,我认为这与问题有关。我的场景是这样的:EditorFor对派生类型不起作用

我有一些业务实体具有公共字段,每个具有该实体唯一的自定义字段。因此,在代码中,这被建模为EntityBase类,并且有许多类派生自此,例如Derived

要制作可重复使用的用户界面,我已经有了一个叫EntityBase.vbhtml认为是这样的:

@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 

,然后一个叫Derived.vbhtml派生类,这样处理:

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

然后,当您导航到\Derived\Edit\123时,它将返回默认视图Derived\Edit.vbhtml,它只是这样做:

@Html.EditorForModel("EntityBase") 

通过这种方式,控制器只是返回预期的默认编辑视图,该视图是对EntityBase视图的单线调用,它执行它的操作并调用Derived来渲染它不知道的派生类。

我以为这不起眼,但它不起作用。如视图代码中所标记的,当我在基类视图中调用EditorForModel时,指定派生类的名称用作模板时,它不会呈现任何内容。我测试过,如果我在顶层编辑模板中调用完全相同的代码行,它可以正常工作。所以有一些关于MVC不喜欢的继承,但我看不到。请帮忙!

更新:它的工作原理,因为我认为这是混淆不是我希望的,如果不是EditorFor我使用Partial(和移动相应的模板,从EditorTemplates文件夹的共享文件夹),但是这并不是一个很好的解决方案遵循EditorFor模板的命名约定。

回答

3

看起来,虽然MVC在这种情况下不会找到命名模板,但如果您指定了模板的完整路径,则会发现它。因此,而不是任何进一步打这个,我采取了以下辅助函数:

<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 

在英语中,这意味着:询问其类型名称的对象,形成以该类型的编辑器模板显式路径,并然后调用HtmlHelper.Partial,指定对象和模板的完整路径。我敢肯定,这可能是更一般的(而不是硬编码的VB),但它的工作原理。

然后使用是这样的:

@Html.EditorForObject(Model) 

,实际上,这是比我要怎样做,这是更混乱甚至更好:

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

即使没有模板查询问题,这将会很方便,因为能够传递一个对象进行编辑(或显示)很方便,而不是只返回该对象的虚拟lambda。

不过,我认为查找问题必须是MVC中的错误。 (如果我有时间,我想我可以检查源代码。)任何人都可以确认或评论这个?

+0

我遇到了同样的问题。感谢您的解决方法。我正要放弃:) –

+0

很高兴听到它!我真的把我的头发弄在这一张上。 –