EditorFor не работает с производным типом - PullRequest
6 голосов
/ 23 ноября 2011

По крайней мере, я думаю, что это связано с проблемой. Мой сценарий таков:

У меня есть несколько бизнес-объектов с общими полями, и у каждого из них есть настраиваемые поля, уникальные для этого объекта. Таким образом, в коде это моделируется как 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")

Таким образом, контроллеры просто возвращают ожидаемое представление Edit по умолчанию, которое представляет собой однострочный вызов представления EntityBase, которое делает свое дело и вызывает Derived для визуализации производного класса, которого у него нет знание.

Я думал, что это ничем не примечательно, но это не работает. Как отмечено в коде представления, когда я вызываю EditorForModel в представлении базового класса, указывая имя производного класса для использования в качестве шаблона, он ничего не отображает. Я проверял, что если я вызову точно такую ​​же строку кода в шаблоне редактирования верхнего уровня, он будет работать нормально. Так что в наследовании есть что-то, что MVC не нравится, но я не вижу, что именно. Пожалуйста, помогите!

Обновление : Это работает так, как я и ожидал, если вместо EditorFor я использую Partial (и перенесу соответствующий шаблон в общую папку из папки EditorTemplates), но это не лучшее решение потому что я думаю, что не следует следовать соглашению об именах шаблонов EditorFor.

1 Ответ

3 голосов
/ 30 ноября 2011

Похоже, что в этом случае 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)

Даже без проблем с поиском по шаблону это было бы удобно, потому что удобно иметь возможность передавать объект для редактирования (или отображения)вместо фиктивной лямбды, которая просто возвращает этот объект.

Тем не менее, я думаю, что проблема поиска должна быть ошибкой в ​​MVC.(Если у меня будет время, я думаю, что смогу проверить исходный код.) Кто-нибудь может подтвердить или прокомментировать это?

...