至少,我认为这与问题有关。我的情况是:
我有许多具有公共字段的业务实体,每个实体都有该实体独有的自定义字段。因此,在代码中,这被建模为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文件夹中移动到Shared文件夹),它可以正常工作,但是这不是一个很好的解决方案,因为我认为不遵循EditorFor模板的命名约定令人困惑。
答案 0 :(得分: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中的一个错误。 (如果我有时间,我想我可以查看源代码。)有人可以确认或评论这个吗?