2
votes

Hi I've been stuck to long on this problem. I've looked at a lot of examples but i cant find what im looking for. Any help is appreciated.

I use the Code-First approach.

I've enabled migration and the database is fine [Student] - [StudentCourse] - [Course].

Scenario: I have two entites -> Student

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual List<Course> Courses { get; set; }
}

And Course

public class Course
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public virtual List<Student> Students { get; set; }
}

Nothing fancy about that... Ive created a ViewModel ->

public class StudentCourseViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }

    public List<Course> Courses { get; set; }
}

View:

@model Project.Web.Models.StudentCourseViewModel @{ ViewBag.Title = "Edit"; }

Edit

@using (Html.BeginForm()) { @Html.ValidationSummary(true)

<fieldset>
    <legend>Student</legend>

    @Html.HiddenFor(model => model.Id)

    <div class="editor-label">
        @Html.LabelFor(model => model.Name)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Name)
        @Html.ValidationMessageFor(model => model.Name)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.Courses)
    </div>
      <div class="editor-field">
    @for (int i = 0; i < Model.Students.Count(); i++)
    {
        <div style="border: dotted 1px; padding: 5px; margin: 10px;">
            @Html.HiddenFor(s => s.Students[i].Id)

            @Html.LabelFor(s => s.Students[i].Name[i + 1])
            @Html.EditorFor(s => s.Students[i].Name)
        </div>
    }
</div>

    <p>
        <input type="submit" value="Save" />
    </p>
</fieldset> }

Controller Action:

    [HttpPost]
    public ActionResult Edit(CourseStudentViewModel model)
    {
        var course = db.Courses.Find(model.CourseId);
        course.Name = model.CourseName;
        course.Description = model.CourseDescription;
        course.Students = model.Students;

        if (ModelState.IsValid)
        {

            db.Entry(course).State = System.Data.EntityState.Modified;
            db.SaveChanges();

            return RedirectToAction("Index");
        }

        return View(model);
    }

(Maby this is were i go wrong...)

Anyway, I want to create a new Student with optional many courses (textboxes -> courseName)

How should i do this?

The main issue is that i always get null values (student is fine, List of courses = NULL) back from my view [httpPost]Create -action.

I'm in need of guidance how to make this approach possible.

Thx J!

1
Are the Courses present in your entity, just not in the ViewModel? Show the code for transforming your entity model into a view model.Kevin Junghans
Can you please post your view code?Corey Adler
@IronMan84 Ive added the view to the postJeppePepp
@KevinJunghans Ive added the controller edit action.JeppePepp
Can you also please post your Create action?Corey Adler

1 Answers

0
votes

Your entities are not setup correctly for a many-to-many relationship. You need another entity to handle the many-to-many mapping. It would look something like this.

public class StudentsToCourses
{
   public int StudentId {get; set;}
   public int CourseId {get; set;}

   public virtual Student Student {get; set;}
   public virtual Course Course {get; set;}
}

Then your student model should be changed to this.

public class Student
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual List<StudentsToCourses> Courses { get; set; }
}

And your coursed model changed to this.

public class Course
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public virtual List<StudentsToCourses> Students { get; set; }
}

You also need to setup the foreign key relationship using the Fluent API. It would look something like this.

public class StudentsToCoursesConfiguration : EntityTypeConfiguration<StudentsToCourses>
{
    internal StudentsToCoursesConfiguration ()
    {
        this.HasKey(p => new {p.StudentId, p.CourseId});
        this.HasRequired(p => p.Student)
            .WithMany(p => p.Courses)
            .HasForeignKey(p => p.StudentId);
        this.HasRequired(p => p.Course)
            .WithMany(r => r.Students)
            .HasForeignKey(p => p.CourseId);

    }
}