0

I have created two models, Student and School and a composite model, StudentSchool. I am using two different partiel views to create one the Student and the other the School. However, in my controller, I am getting null values for both the Student and School. Below is my code:

Student:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace LayoutProject.Models
{
    public class Student
    {
        public int studentID { get; set; }
        public String firstname { get; set; }
        public String lastname { get; set; }
        public int year { get; set; }
    }
}

School:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace LayoutProject.Models
{
    public class School
    {
        public int schoolID { get; set; }
        public String name { get; set; }
        public String add { get; set; }
    }
}

Composite model, StudentSchool:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;


namespace LayoutProject.Models
{
    public class StudentSchool
    {
        public Student student { get; set; }
        public School school { get; set; }
    }
}

PartielViewStudent:

   @model LayoutProject.Models.Student

<h4>Student</h4>

            @Html.LabelFor(d=>d.studentID) : @Html.TextBoxFor(d=>d.studentID)

            <br />
            @Html.LabelFor(d=>d.firstname) : @Html.TextBoxFor(d=>d.firstname)

            <br />
            @Html.LabelFor(d=>d.lastname) : @Html.TextBoxFor(d=>d.lastname)

            <br />
            @Html.LabelFor(d=>d.year) : @Html.TextBoxFor(d=>d.year)

            <br />

PartialViewSchool:

    @model LayoutProject.Models.School

<h4>School</h4>


        @Html.LabelFor(d=>d.schoolID) : @Html.TextBoxFor(d=>d.schoolID)

        <br />
        @Html.LabelFor(d=>d.name) : @Html.TextBoxFor(d=>d.name)

        <br />
        @Html.LabelFor(d=>d.add) : @Html.TextBoxFor(d=>d.add)

        <br />

The View:

    @{
    ViewBag.Title = "StudentSchool";
}


<h2>StudentSchool</h2>
<form action="/Home/CreateStudentSchools" method="post">

    @using (Html.BeginForm())
    {


        @Html.Partial("_PartialViewStudent")

        @Html.Partial("_PartialViewSchool")
    }

    <input id="createSD" type="submit" value="Submit"/>
</form>

The controller:

 [HttpPost]
        public ActionResult CreateStudentSchools(StudentSchool ss)
        {
            return View("CreateStudentSchool");
        }

Any idea what I might be missing here? Been with this since 4 days.

refresh
  • 1,319
  • 2
  • 20
  • 71
  • Your generating inputs with `name="studentID"` when you need to be creating `name="Student.studentID"` in order to bind to your model. You should be using an `EditorTemplate`, and `EditorFor(m => m.Student)`, not a partial. –  Oct 01 '15 at 06:37
  • Also you should make use of your composite model e.g.... `@model LayoutProject.Models.StudentSchool.student` you are looking for StudentSchool in the controller but from what I can see you never populate it – hjardine Oct 01 '15 at 06:41
  • @Stephen Muecke: I was asked to use only partial views... – refresh Oct 01 '15 at 06:42
  • @hjardine: I don't get what you mean. Where should I populate StudentSchool? – refresh Oct 01 '15 at 06:44
  • I have added an alternative for that in my answer, but the correct usage is an `EditorTemplate` –  Oct 01 '15 at 06:44
  • @tabby Follow Stephens answer, should work fine – hjardine Oct 01 '15 at 06:45
  • @hjardine: Yep, you are right! Thanks a lot! – refresh Oct 01 '15 at 07:46

2 Answers2

4

Move you 'partial' views into the /Views/Shared/EditorTemplates folder and rename them to Student.cshtml and School.cshtml respectively (to match the names of the classes). Then in the main view use

@using (Html.BeginForm())
{
    @Html.EditorFor(m => m.Student)
    @Html.EditorFor(m => m.School)
}

The inputs your generating will now contain the correct name attribute for binding to your view model, for example name="Student.studentID" instead of the current name="studentID"

Note: As an alternative, you can pass the HtmlFieldPrefix to a Partial as indicated in this answer.

Community
  • 1
  • 1
-1

Its not a good idea if you provide the two partial views with different models and combining in one model.You have to pass the reference of the composite model to your partial views.

 @using (Html.BeginForm())
{


    @Html.Partial("_PartialViewStudent",Model.student)

    @Html.Partial("_PartialViewSchool",Model.school)
}

This will work fine as with this approach as everything in the form is strictly typed.

In partial views also you have to specify models as

@model LayoutProject.Models.StudentSchool.student

@model LayoutProject.Models.StudentSchool.school

I am not sure about your [httpget] create method but it should be like [HttpGet] public ActionResult CreateStudentSchools(StudentSchool ss) { var studentsc=new StudentSchool() { student=new Student(), school=new School() } return View("CreateStudentSchool",studentsc); }

Prashant Mohite
  • 758
  • 2
  • 7
  • 19
  • When I try this : @Html.Partial("_PartialViewStudent",Model.student), I get an error: {"Object reference not set to an instance of an object."} – refresh Oct 01 '15 at 06:57
  • @tabby, You need to pass a model to the partial - either initialize a default `Student` and `School` in the controller, or use `@Html.Partial("_PartialViewStudent", new Student())` - But this wont work anyway - it will not add the prefix to the `name` attribute so binding will fail when you post. –  Oct 01 '15 at 07:25
  • @Prashant Mohite: I did that as well but same error. I guess the best way is to use Editor Templates as in the first answer. I appreciate your help and quick response to my answers. Thanks a lot. – refresh Oct 01 '15 at 07:43
  • @PrashantMohite, Your edited code will NOT work - it cannot bind to `StudentSchool` when the form is submitted. –  Oct 01 '15 at 07:48