I have been following the Microsoft Contoso MVC3 University Tutorial located here
I have a question regarding one area, In part 6; the tutorial explains how to create a table of courses an instructor can be assigned to using checkboxes. Specifically from the heading “adding Course Assignments to the Instructor Edit Page” onward
It seems overly complex, is there a more efficient way of doing things? Plug-in/built-in system etc.
What if you wanted to expand the system so an instructor had more than just Courses assigned to him? The duplication of code would be huge.
InstructorController
// GET: /Instructor/Edit/5
public ActionResult Edit(int id)
{
Instructor instructor = db.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.Courses)
.Where(i => i.InstructorID == id)
.Single();
PopulateAssignedCourseData(instructor);
return View(instructor);
}
private void UpdateInstructorCourses(string[] selectedCourses, Instructor instructorToUpdate)
{
if (selectedCourses == null)
{
instructorToUpdate.Courses = new List<Course>();
return;
}
var selectedCoursesHS = new HashSet<string>(selectedCourses);
var instructorCourses = new HashSet<int>
(instructorToUpdate.Courses.Select(c => c.CourseID));
foreach (var course in db.Courses)
{
if (selectedCoursesHS.Contains(course.CourseID.ToString()))
{
if (!instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.Courses.Add(course);
}
}
else
{
if (instructorCourses.Contains(course.CourseID))
{
instructorToUpdate.Courses.Remove(course);
}
}
}
}
private void PopulateAssignedCourseData(Instructor instructor)
{
var allCourses = db.Courses;
var instructorCourses = new HashSet<int>(instructor.Courses.Select(c => c.CourseID));
var viewModel = new List<AssignedCourseData>();
foreach (var course in allCourses)
{
viewModel.Add(new AssignedCourseData
{
CourseID = course.CourseID,
Title = course.Title,
Assigned = instructorCourses.Contains(course.CourseID)
});
}
ViewBag.Courses = viewModel;
}
edit.cshtml
int cnt = 0;
List<UniversitySystem.ViewModels.AssignedCourseData> courses = ViewBag.Courses;
foreach (var course in courses)
{
if (cnt++ % 3 == 0)
{
@: </tr> <tr>
}
@: <td>
<input type="checkbox"
name="selectedCourses"
value="@course.CourseID"
@(Html.Raw(course.Assigned ? "checked=\"checked\"" : "")) />
@course.CourseID @: @course.Title
@:</td>
}
@: </tr>
}
</table>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
ViewModels/AssignedCourseData.cs
public class AssignedCourseData
{
public int CourseID { get; set; }
public string Title { get; set; }
public bool Assigned { get; set; }
}
}
A great deal of code to effectivly create this screen:

I guess you could generalise the helper methods used in the InstructorController, but that is no small task.
It seems such a fundamental component of CRUD systems to deal with one/many to many relationships; I am surprised I cannot find information on the topic.
TLDR: Is there a better way to associate objects to other objects using MVC3/Entity framework than what is shown above.
Edit2:
Here’s an image of a quick Lightswitch application

A Candidate can have a number of Skills, Disabilities and Offences related to them. If i were to implement a MVC version of this system i would x3 of the code listed above to create the same effect.
Surely there is a more efficient solution.
It seems, based on your comments, that you are looking for MVC to be Lightswitch. If that were the case, Microsoft would not have developed Lightswitch.
Microsoft offers many technologies, MVC, Web Pages (WebMatrix), WebForms, LightSwitch. Each has it’s own unique strengths and weaknesses, and you choose the technology that fits your requirements the best.
If you’re developing in MVC, you need to expend more effort in writing presentation code. But, this extra effort gives you excellent flexibility in how that presentation works, what it looks like, and how it behaves. If you don’t want to do that, then I suggest choosing a different technology.