Monday, November 23, 2015

How to use multiple Models in a View - ASP.NET MVC 4

When I was a beginner for ASP.NET MVC, I faced a question many times: how many ways do you know to use/pass multiple models in/to a view? At that time, I knew only two ways, then I learned some other ways to achieve the same. In this article, I will share my learning so far. Hope it will be helpful for others.

There are many ways of using multiple models in a view, most frequently used are given below:
  • ViewData
  • ViewModel
  • PartialView
  • ViewBag
  • TempData
  • Tuple
All the above ways of using multiple models in view have their place but we need to think and pick which one fits our requirements. 

Creating Sample Demo :
Let's get started by creating a sample demo application. Follow the below steps:

01.  Open Visual Studio 2013, select ASP.NET MVC4 Web Application template and give it project name asMultipleModelDemo and click OK. 


02.  Select a template as Basic application then click OK. Visual Studio adds a MultipleModelDemo project in solution as shown below in screenshot.


03.  Right click on the Models folder, add a Models.cs file. Now we need to add three models named as CourseInstitute and Student by writing the following code as shown below:

public class Course
{
    public int CourseId { get; set; }
    public string CourseName { get; set; }
}

public class Institute
{
    public int InstituteId { get; set; }
    public string InstituteName { get; set; }
    public List<Course> AllotedCourses { get; set; }
}

public class Student
{
    public int EnrollmentNo { get; set; }
    public string StudentName { get; set; }
    public List<Course> EnrolledCourses { get; set; }
}

04.  Add a class file under the Models folder named as Repository.cs file, which will have the implementation of methods to get hard-coded data for application in order to keep it convenient.
Following is the code for GetCourse method which will return a list of courses.

public List<Course> GetCourses()
{
    return new List<Course> { 
        new Course () {  CourseId = 1, CourseName = "Chemistry"}, 
        new Course () {  CourseId = 2, CourseName = "Physics"},
        new Course () {  CourseId = 3, CourseName = "Math" },
        new Course () {  CourseId = 4, CourseName = "Computer Science" }
    };
}           


Following is the code GetFaculties method which will return a list of faculties:
public List<Institute> GetInstitutes()
{
    return new List<Institute> {                 
        new Institute() {  InstituteId = 1, InstituteName = "SITEM",
            AllotedCourses = new List<Course> 
            {new Course () { CourseId = 1, CourseName = "Chemistry"},
                             new Course () { CourseId = 2, CourseName = "Medicine"},
                             new Course () { CourseId = 3, CourseName = "Bussiness Mgmt."},
        }}, 
        new Faculty () {  InstituteId = 2, InstituteName = "SLIIT" ,
            AllotedCourses = new List<Course> 
            {new Course () { CourseId = 2, CourseName = "Engineering"},
                             new Course () { CourseId = 4, CourseName = "Computer Science"}
        }},
        new Faculty () {  InstituteId = 3, InstituteName = "NIBM", 
            AllotedCourses = new List<Course> 
            {new Course () { CourseId = 3, CourseName = "Software Eng."},
                             new Course () { CourseId = 4, CourseName = "Hotel Mgmt."}
        }}
    };
}           

Following is the code for GetStudents method which will return a list of students:
public List<Student> GetStudents()
{
    List<Student> result = new List<Student> { 
        new Student () { EnrollmentNo = 1, StudentName= "Sumudu", 
            EnrolledCourses = new List<Course> 
            { new Course () { CourseId = 1, CourseName = "Chemistry"},
                              new Course () { CourseId = 2, CourseName = "Physics"},
                              new Course () { CourseId = 4, CourseName = "Computer Science"}
        }},
        
        new Student () {  EnrollmentNo = 2, StudentName= "Lakshan",
            EnrolledCourses = new List<Course> 
            { new Course () { CourseId = 2, CourseName = "Physics"} ,
                              new Course () 
                              { CourseId = 4, CourseName = "Computer Science"}
        }},
        
        new Student () {  EnrollmentNo = 3, StudentName= "Sampath",
            EnrolledCourses = new List<Course>
            {  new Course () { CourseId = 3, CourseName = "Math"},
                               new Course () { CourseId = 4, CourseName = "Computer Science"}
        }}
    };
    
    return result;
}           


05.  Add a HomeController to Controller folder. We will write the code in HomeController later. 

06.  In Shared folder, we will modify the existing code in _Layout.cshtml file. write the following code in body tag:

body>
    @* Define the place for navigation links in left side of the page*@
    <div class="navigationPanel">
        <div style="margin: 40px 25px 2px 25px;">
            <h3>Links to Demostrations</h3>

So far, we have created basic code which we will be using in all scenarios. Further, we will learn each scenario one by one.

Passing Multiple Models using ViewBag

ViewBag is also used to pass data from a controller to a view. It is a dynamic property which comes inControllerBase class that is why it doesn’t require typecasting for datatype.
  1. Add the following code in HomeController:
    public ActionResult ViewBagDemo()
    {
        ViewBag.Courses = _repository.GetCourses();
        ViewBag.Students = _repository.GetStudents();
        ViewBag.Faculties = _repository.GetFaculties();
        return View();
    }            
    Here ViewBagDemo action method will be passing data to view (ViewBagDemo.cshtml) file usingViewBag.
  2. Add a view named as ViewBagDemo. All code will be same as you have written in ViewDataDemo.cshtmlfile. Just modify input model to foreach function.
    @*Iterating Course model using ViewBag *@
    @foreach (var item in ViewBag.Courses)
    {         
        <option>@item.CourseName</option>
  3. In script tag, replace the following line of code in getInstituteTable function:
    //Get all Institutes with the help of model 
    // (ViewBag.Institutes), and convert data into json format.                
    var allInstitutes = @Html.Raw(Json.Encode(ViewBag.Institutes));
  4. Replace the following line of code in getStudentTable function:
    //Get all students with the help of model(ViewBag.Students), 
    //and convert data into json format.
    var allStudents = @Html.Raw(Json.Encode(ViewBag.Students));

Passing Multiple Models using PartialView

Partial view is used where you need to share the same code (Razor and HTML code) in more than one view. For more details about PartialView, please visit here.
  1. In Home controller, add the following code, PartialViewDemo action method will return a view having the list of all courses only. This action method will not have or pass any faculty or student information as of now.
    public ActionResult PartialViewDemo()
    {
        List<Course> allCourse = _repository.GetCourses();
        return View(allCourse);
    }            
  2. Add a view named as PartialViewDemo. All HTML code will be same as you have written before. Just modify foreach function.
    @*Iterating Course Model*@
    @foreach(var item in Model)
    {         
        <option>@item.CourseName
        </option>
  3. In script tag, modify getInstituteTable function as written below:
    function getInstituteTable() {
      $.ajax({
             // Get Institute PartialView
             url: "/Home/InstituteToPVDemo",
         type: 'Get',
         data: { courseName: selectedCourseName },
         success: function (data) {
            $("#InstituteDetailTable").empty().append(data);
         },
         error: function () {
            alert("something seems wrong");
     }
      });
    }
  4. Modify getStudentTable function as written below:
        function getStudentTable() {
        $.ajax({
            // Get Student PartialView
            url: "/Home/StudentsToPVDemo",
            type: 'Get',
            data: { courseName: selectedCourseName },
            success: function (data) {
                $("#studentDetailTable").empty().append(data);
            },
            error: function () {
                alert("something seems wrong");
            }
        });
    }        
  5. Add a new Action method in HomeController as StudentsToPVDemo and add the following code in StudentsToPVDemo action method.
    public ActionResult StudentsToPVDemo(string courseName)
    {
        IEnumerable <Course> allCourses = _repository.GetCourses();
        var selectedCourseId = (from c in allCourses where 
        c.CourseName == courseName select c.CourseId).FirstOrDefault();
        
        IEnumerable <Student> allStudents = _repository.GetStudents();
        var studentsInCourse = allStudents.Where(s => 
        s.EnrolledCourses.Any(c => c.CourseId == selectedCourseId)).ToList();
        
        return PartialView("StudentPV", studentsInCourse); 
    }
  6. Add a PartialView to the Shared folder by right clicking on StudentsToPVDemo action method, give it name as StudentPVStudentsToPVDemo action will return StudentPV PartialView having the list of students studying in a particular course.
  7. Add the following code in StudentPV.cshtml file.
    @model  IEnumerable <MultipleModelDemo.Models.Student>
     <table id="tblFacultyDetail" class="tableStyle">
             <tr>
             <th class="tableHeader" style="width:60px;">Roll No </th>
  8. Add a new action method to call PatialView for faculties in HomeController. Name it asFacultiesToPVDemo and add the following code:
    public ActionResult InstitutesToPVDemo(string courseName)
    {
        IEnumerable <Course> allCourses = _repository.GetCourses();
        var selectedCourseId = (from c in allCourses where 
        c.CourseName == courseName select c.CourseId).FirstOrDefault();
        
        IEnumerable <Faculty> allFaculties = _repository.GetInstitutes();
        var InstitutessForCourse = allInstitutes.Where(f => 
        f.AllotedCourses.Any(c =>  c.CourseId == selectedCourseId)).ToList();
        
        return PartialView("FacultyPV", InstitutessForCourse);
      }            
  9. Add a PartialView named as InstitutePV as we did for student PartialView, write the same code as you have written in StudentPV.cshtml file. Just replace one line of code as:
    @model  IEnumerable<MultipleModelDemo.Models.Institute>
  10. FacultiesToPVDemo action will return InstitutePV PartialView having the list of faculties who teach a particular course.

Conclusion

In this article, we learned how to use multiple models in a view. In this article I explained only two approaches.  I will share my findings about when and where to pick a particular way to use multiple models in a view later and other approaches as well.

No comments:

Post a Comment

How to use Ajax.ActionLink and Html.ActionLink in MVC

Html.ActionLink   Html.ActionLink creates a hyperlink on a view page and the user clicks it to navigate to a new URL. It does not ...