EditorFor不适用于派生类型

时间:2022-08-04 13:57:59

At least, I think that's related to the problem. My scenario is this:

至少,我认为这与问题有关。我的情况是这样的:

I've got a number of business entities with common fields, and each one has custom fields unique to that entity. So in code, this is modeled as an EntityBase class, and there are a number of classes derived from this, e.g., Derived.

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

To make a reusable UI, I've got a view called EntityBase.vbhtml that looks like this:

为了创建一个可重用的UI,我有一个名为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

and then one called Derived.vbhtml for the derived classes that does this:

然后一个名为Derived.vbhtml的派生类执行此操作:

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

Then, when you navigate to \Derived\Edit\123, it returns the default view Derived\Edit.vbhtml, which just does this:

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

@Html.EditorForModel("EntityBase")

In this way, controllers just return the expected default Edit view, which is a one-liner call to the EntityBase view, which does its thing and invokes the Derived to render the derived class stuff that it has no knowledge of.

通过这种方式,控制器只返回预期的默认Edit视图,这是对EntityBase视图的单行调用,它实现了它的功能并调用Derived来呈现它不知道的派生类内容。

I thought this was unremarkable, but it doesn't work. As marked in the view code, when I call EditorForModel within the base class view, specifying the name of the derived class for use as a template, it doesn't render anything. I've tested that if I call this exact same line of code in the top level Edit template, it works fine. So there's something about the inheritance that MVC doesn't like, but I can't see what. Please help!

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

Update: It works as I would expect if instead of EditorFor I use Partial (and move the corresponding template to the Shared folder from the EditorTemplates folder), but that's not a great solution because I think it's confusing not to follow the naming convention for EditorFor templates.

更新:它可以正常工作,而不是EditorFor我使用Partial(并将相应的模板从EditorTemplates文件夹移动到Shared文件夹),但这不是一个很好的解决方案,因为我认为不遵循EditorFor的命名约定令人困惑模板。

1 个解决方案

#1


3  

It appears that, while MVC won't locate the named template in this circumstance, it will find it if you specify the full path to the template. So, rather than fight this any further, I implemented the following helper function:

看起来,虽然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

In English, this means: ask the object for its type name, form the explicit path to the editor template for that type, and then invoke HtmlHelper.Partial, specifying the object and the full path to the template. I'm sure this could be more general (and not hardcoded for vb), but it works.

在英语中,这意味着:询问对象的类型名称,形成该类型的编辑器模板的显式路径,然后调用HtmlHelper.Partial,指定对象和模板的完整路径。我确信这可能更通用(而不是硬编码为vb),但它确实有效。

Then the usage is like this:

那么用法是这样的:

@Html.EditorForObject(Model)

and actually, this is even better than what I was trying to do, which is much messier:

实际上,这甚至比我试图做的更好,这更麻烦:

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

Even without the template lookup problem, this would be handy, because it's convenient to be able to pass an object for editing (or display), rather than a dummy lambda that just returns that object.

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

Still, I think the lookup problem must be a bug in MVC. (If I ever get time, I guess I can check the source code.) Can anyone confirm or comment on this?

不过,我认为查找问题必定是MVC中的一个错误。 (如果我有时间,我想我可以查看源代码。)任何人都可以对此进行确认或评论吗?

#1


3  

It appears that, while MVC won't locate the named template in this circumstance, it will find it if you specify the full path to the template. So, rather than fight this any further, I implemented the following helper function:

看起来,虽然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

In English, this means: ask the object for its type name, form the explicit path to the editor template for that type, and then invoke HtmlHelper.Partial, specifying the object and the full path to the template. I'm sure this could be more general (and not hardcoded for vb), but it works.

在英语中,这意味着:询问对象的类型名称,形成该类型的编辑器模板的显式路径,然后调用HtmlHelper.Partial,指定对象和模板的完整路径。我确信这可能更通用(而不是硬编码为vb),但它确实有效。

Then the usage is like this:

那么用法是这样的:

@Html.EditorForObject(Model)

and actually, this is even better than what I was trying to do, which is much messier:

实际上,这甚至比我试图做的更好,这更麻烦:

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

Even without the template lookup problem, this would be handy, because it's convenient to be able to pass an object for editing (or display), rather than a dummy lambda that just returns that object.

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

Still, I think the lookup problem must be a bug in MVC. (If I ever get time, I guess I can check the source code.) Can anyone confirm or comment on this?

不过,我认为查找问题必定是MVC中的一个错误。 (如果我有时间,我想我可以查看源代码。)任何人都可以对此进行确认或评论吗?