5

Take the following models as an example:

namespace MyNamespace.Model
{
    //you can only have two friends for the sake of simplicity in this example :P
    public class Friends{
        public Person NormalFriend { get; set; }
        public Hipster HipsterFriend { get; set; }
    }

    public class Person{
        public string Name { get; set; }
        public string PhoneNumber { get; set; }
    }

    public class Hipster : Person
    {
        public HatType HatPreference { get; set; }
        public int CoolPoints { get; set; }
    }
}

Let's say we're trying to add our two friends, a normal friend and a hipster friend:

Create.cshtml:

@model MyNamespace.Model.Friends

<div class='container'>
    @using (Html.BeginForm())
    {
        @Html.ValidationSummary(true)
        @Html.AntiForgeryToken()

        @Html.EditorFor(model => model.NormalFriend) //uses Person EditorTemplate by convention

        @Html.EditorFor(model => model.HipsterFriend) //uses Hipster EditorTemplate by convention
</div>

EditorTemplates/Person.cshtml:

@model MyNamespace.Model.Person

<div class='row'>
    <div class='col'>
        @Html.EditorFor(model => model.Name)
    </div>
    <div class='col'>
        @Html.EditorFor(model => model.PhoneNumber)
    </div>
</div>

EditorTemplates/Hipster.cshtml:

@model MyNamespace.Model.Hipster

@Html.EditorFor(model => model, "Person") // <-- what I've tried and it isn't working

<div class='row'>
    <div class='col'>
        @Html.EditorFor(model => model.CoolPoints)
    </div>
    <div class='col'>
        @Html.EditorFor(model => model.HatPreference)
    </div>
</div>

In the Hipster EditorTemplate, the code

@Html.EditorFor(model => model, "Person")

should pass the Hipster model to the Person EditorTemplate so that I don't have to repeat the Templated Code for shared properties (of the base type Person).

Currently, the above code just completely ignores the EditorFor and only displays the Hipster specific properties(ie CoolPoints and HatPreference).

Alternatively, I could change the following code in Create.cshtml:

 @Html.EditorFor(model => model.NormalFriend) 

 @Html.EditorFor(model => model.HipsterFriend) 

to:

 @Html.EditorFor(model => model.NormalFriend) 

 @Html.EditorFor(model => model.HipsterFriend, "Person") //break convention and the idea of nesting     
 @Html.EditorFor(model => model.HipsterFriend) 

which will achieve what I want, but it seems wrong that I am unable to do this in the Hipster EditorTemplate.

Is my logic flawed on this or am I missing something? I thought it possibly could be disregarding the line in question for fear of recursion but the templateName argument should clarify. This idea of inheriting the base type and nesting works with partials but partials don't handle ViewData.TemplateInfo.GetFullHtmlFieldNames of complex objects which are necessary for validation.


This question is related: In an Editor Template call another Editor Template with the same Model although the solution isn't applicable in my situation. Is there a workaround to nest the views without using partials or is that my only way?
Community
  • 1
  • 1
Carrie Kendall
  • 11,124
  • 5
  • 61
  • 81
  • Can you explain why you can't use a partial in your template? – Yishai Galatzer May 06 '14 at 19:36
  • AFAIK, partials don't retain parent property information. So you will get duplicate `ids` and `names` and will be unable to differentiate between `NormalFriend` and `HipsterFriend` properties (ie `EditorFor(model => model.Name)` would return something like `` rather than `` – Carrie Kendall May 06 '14 at 19:47

0 Answers0