0

I am working on a form with a parent child (one to many) relationship using MVC 5 / EF 6.1. I am trying to render the childs via a partial view that will not render or give me any errors (on creating a new form). I tried running the debugger and I did not see anything wrong (I'm sure there is though).

So far this is what I have:

Models

public class Parent
{

    public int ParentID { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }

    public virtual ICollection<Child> Childs { get; set; }

}
public class Child
{
    public int ChildID { get; set; }
    public int ParentID { get; set; }

    public string Name { get; set; }
    public string DOB { get; set; }
    public string Address { get; set; }

    public virtual Parent Parent { get; set; }
}

ViewModels

public class ParentVM
{

    public ParentVM()
    {
        //Children = new List<ChildVM>()
           // {
              //  new ChildVM(){Name="1", DOB="1", Address="1"},
              //  new ChildVM(){Name="1", DOB="1", Address="1"},
              //  new ChildVM(){Name="1", DOB="1", Address="1"},                    
            //};

         Children = new List<ChildVM>(); 
    }


    public int ParentID { get; set; }
    public int ChildID { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }

    public string Name { get; set; }
    public string DOB { get; set; }
    public string Address { get; set; }

    public IList<ChildVM> Children { get; set; }

}

public class ChildVM
{
    public int ChildID { get; set; }
    public int ParentID { get; set; }

    public string Name { get; set; }
    public string DOB { get; set; }
    public string Address { get; set; }
}

View (created via scaffolding: Index, Details, Edit, Create, Delete)

@model SomeNamespace.ViewModels.ParentVM
@{ViewBag.Title = "Create";}

<h2>Create</h2>

@using (Html.BeginForm()) 
{
@Html.AntiForgeryToken()

<div class="form-horizontal">
    <h4>Parent</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })


    <div class="form-group">
        @Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.FirstName, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.LastName, "", new { @class = "text-danger" })
        </div>
    </div>


    <table border="1">
        <tr>
            <th>Name</th>
            <th>DOB</th>
            <th>Address</th>
        </tr>
        @Html.EditorFor(x => x.Children)
    </table>


    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</div>}

<div>@Html.ActionLink("Back to List", "Index")</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")}

Partial View (Views/Shared/EditorTemplates/Child.cshtml)

@model SomeNamespace.Models.Child
<tr>
<td>
    @Html.EditorFor(model => model.Name)
</td>
<td>
    @Html.EditorFor(model => model.DOB)
</td>
<td>
    @Html.EditorFor(model => model.Address)
</td>

Controller (ParentsController.cs)

// GET: Parents/Create
    public ActionResult Create()
    {

        //var viewModel = new ParentVM
        //{
        //    Children =
        //        new List<ChildVM>()
        //    {                    
        //       new ChildVM() {Name="1", DOB="1", Address="1"},
        //       new ChildVM() {Name="1", DOB="1", Address="1"},
        //       new ChildVM() {Name="1", DOB="1", Address="1"}
        //    }
        //};

        return View(new ParentVM());
        //return View(viewModel);
    }

// POST: Parents/Create
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "ParentID,FirstName,LastName, Name")] ParentVM viewModel)
    {
        if (ModelState.IsValid)
        {


            var child = new Child()
            {
                //Name = viewModel.Name,
                //DOB = viewModel.DOB,
                //Address = viewModel.Address


            };


            var parent = new Parent()
            {
                //FirstName = viewModel.FirstName,
                //LastName = viewModel.LastName

            };

            db.Parents.Add(parent);
            db.Childs.Add(child);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(viewModel);
    }

This is what I see in the view source:

<table border="1">
        <tr>
            <th>Name</th>
            <th>DOB</th>
            <th>Address</th>
        </tr>

    </table>

Maybe it does not like the type? I thought you were able to use a model in a partial view (editorTemplates)??

Hockey_Fan
  • 99
  • 10
  • I'm guessing maybe you just didn't include this code, but I don't see anywhere that you actually add any children (`Children` is an empty list). You would get the result you're seeing with zero children. – jdmcnair Nov 24 '14 at 02:38

1 Answers1

0

You ParentVM class contains a property public IList<ChildVM> Children { get; set; } but your EditorTemplate is for @model SomeNamespace.Models.Child. Change it to

@model SomeNamespace.Models.ChildVM

And rename your EditorTemplate to match

Views/Shared/EditorTemplates/ChildVM.cshtml

  • I tried that, I tried with ParentVM. I always gives me the same result. – Hockey_Fan Nov 24 '14 at 02:27
  • Your also need to change the name of the `EditorTemplate` to match! `Views/Shared/EditorTemplates/ChildVM.cshtml` –  Nov 24 '14 at 02:29
  • Ok, I just renamed my editor template to ChildVM, I still get the same result. Also, my view models are in a ViewModels folder, so I changed it like so : @model SomeNamespace.ViewModels.ChildVM – Hockey_Fan Nov 24 '14 at 02:32
  • You have just edited your question and commented out the creation of the new `ChildVM` objects in the `ParentVM` constructor so the list is empty - so there is nothing to display! –  Nov 24 '14 at 02:35
  • You are correct, I did change it and it was returning 000
    Name DOB Address
    – Hockey_Fan Nov 24 '14 at 02:40
  • So now it works! Awesome. That was quick. So I was pretty close huh for a newbie? How is the rest looking so far, I know my controller (HttpPost) will need work to update the database. I really appreciate your help. – Hockey_Fan Nov 24 '14 at 02:42
  • Few other comments. `DOB` I assume is `DateOfBirth` so why is it a `string` and not `DateTime`? Just use `@Html.TextBoxFor()` for your `string` types. Including `public int ParentID { get; set; }` in the view model seems pointless and you have not included an ID property (not necessary in a create method since it does not exist in the db, but might be necessary in an edit form). And remove the `[Bind(Include="..")]` from the POST method (your actually excluding the `Children`!). You should never need to use a `BindAttribute` if you have a view model. –  Nov 24 '14 at 02:51
  • Awesome. All good points. I will make those changes as well. Thanks so much. I really appreciate you taking the time to help me. Have a great day! – Hockey_Fan Nov 24 '14 at 02:56