EditorFor does not work on derived type

At least I think this is due to the problem. My scenario is this:

I have several business objects with common fields, and each of them has special fields unique to this object. Thus, in the code, this is modeled as an EntityBase class, and from this there are a number of classes, for example Derived .

To make the reusable user interface, I have a view called EntityBase.vbhtml that looks like this:

 @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 derived classes that does this:

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

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

 @Html.EditorForModel("EntityBase") 

Thus, the controllers simply return the expected default change, which is a one-line call to the EntityBase , which does its thing, and calls Derived to render the derived class that does not have knowledge.

I thought it was unremarkable, but it does not work. As noted in the view code, when I call EditorForModel in the view of the base class, specifying the name of the derived class to use as a template, it does not display anything. I tested that if I name this same line of code in a top-level editing template, it works fine. So something about inheritance that MVC doesn't like, but I don't see that. Please, help!

Refresh . It works the way I would expect if I use Partial instead of EditorFor (and move the corresponding template to the shared folder from the EditorTemplates folder), but this is not wonderful because I think it is confused so as not to follow the naming convention for EditorFor templates .

+6
source share
1 answer

It seems that although MVC will not find the named template in this case, it will find it if you specify the full path to the template. Therefore, instead of fighting this further, I implemented the following helper function:

 <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 an explicit path to the editor template for this type, and then call HtmlHelper.Partial, specifying the object and the full path to the template. I'm sure this may be more general (and not hardcoded for vb), but it works.

Then use will look like this:

 @Html.EditorForObject(Model) 

and in fact, this is even better than what I tried to do, which is much merciless:

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

Even without the problem of finding a template, this would be convenient, because it was convenient to be able to pass an object for editing (or display), rather than a dummy lambda that simply returns that object.

However, I think the search problem should be a bug in MVC. (If I ever find time, I think I can check the source code.) Can someone confirm or comment on this?

+3
source

Source: https://habr.com/ru/post/902225/


All Articles