Cascading Dropdowns in Asp.net MVC3 Razor using ajax, jQuery and Entity Framework


Short Description :

1. We will have two tables in DB to populate two dropdowns. First dropdown will be populated on load from first table. On change of value in First dropdown, second dropdown will be populated using the second table.
2. We will use ajax post using jQuery to fetch the data corresponding to value selected in first dropdown and the list will be appended to second dropdown.
3. We are going to use Entity Framework and database first approach as ORM. We will create our DB first and then will create out EF classes out of that.




Database :

First Table : We have CarCompany as our first simple table. This table holds an Id and company name. Id is our primary key integer and company name is nvarchar to hold string values. The table design is shown below :


Second Table : We have CarModel as our second table. This table has Id, CarName and CarCompanyId as column. Id is the primary key for this table, CarName will hold the name of the car and CarCompanyId is the foreign key which refers the Id column of CarCompany table. The table design is shown below :



Entity Framework :

Add an .edmx file in your solution. Open the edmx, right click on it and click generate model from database.


On clicking Update Model from Database, will generate our classes. This approach is called as Database First approach where in we create out database first and then create our model classes using database. 

The classes generated from Database. The CarModel holds the reference of CarCompany class. The relationship between the two is o or 1 to many.


Controller :

We have created a Car controller. We have also created a method named Cascading which will be called first and this method will query DB to fetch CarCompany data and fill the first dropdown. Cascading action method looks like below :


public ActionResult Cascading()
        {
            //Creating object of Service class Car. We have a separate service class to query to DB.
            Car carService = new Car();
            //Creating object of ViewModel which will pass as model to the view.
            CarViewModel model = new CarViewModel();
            //Creating IEnumerable list of SelectedListItem.
            List<SelectListItem> listcompanies = new List<SelectListItem>();
            //Creating List of CarCompany object which will hold the list of CarCompany objects from DB.
            List<CarCompany> carCompanies = new List<CarCompany>();
            //We are populating list by calling GetCompanyListFromDB method of service, which will bring 
            //all the record of CarCompany table from db
            carCompanies =  carService.GetCompanyListFromDB();
            //We are adding Select as first item of out Selected List
            listcompanies.Add(new SelectListItem { Text = "Select", Value = "Select", Selected = true });
            //We are iterating through the CarCompanyList and are using Company name and Id to create SelectedList.
            foreach (CarCompany item in carCompanies)
            {
                listcompanies.Add(new SelectListItem { Text = item.companyName,Value=item.Id.ToString() });
            }
            //Selected List is assigned to model's property.
            model.listCarCompany = listcompanies;
            //View is returned with model as parameter.
            return View(model);
        }


We have another action method which returns json result. When user selects some value in the dropdown. The dropdown value is posted to this method using ajax and jQuery as a parameter. The method based on the parameter queries the CarModel table i.e. second table and returns the list in json form.



[HttpPost]
        //Gets the Cars based on the company selected in first Dropdown.
        //Method accepts selectedValue as parameter. This is basically the selected value of first dropdown.
        public ActionResult GetCarsBycompany(string selectedValue)
        {
            //Created object of service class which holds the method that queries database.
            Car carService = new Car();
            //Created a list of string to hold car names from Database.
            List<string> carList = new List<string>();
            //Populating the list by calling GetCarsByCompanyId method of service class.
            carList = carService.GetCarsByCompanyId(Convert.ToInt32(selectedValue));
            //Returning the list using jSon.
            return Json(new { CarList = carList });
        }

Service Class :


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

namespace CascadingDropdowns.Service
{
    public class Car
    {
        //Gets the CarCompany List from DB.
        public List<CarCompany> GetCompanyListFromDB()
        {
            //Created DataContext to query DB.
            using(CascadingDropdownEntities dataContext = new CascadingDropdownEntities())
            {
                //returns all the records present in CarCompany table in list format.
                return dataContext.CarCompanies.ToList();
            }
        }

        //Gets the CarModel list based on CompanyId which is foreign key in Carmodel table.
        public List<string> GetCarsByCompanyId(int companyId)
        {
            //Created DataContext to query DB.
            using (CascadingDropdownEntities dataContext = new CascadingDropdownEntities())
            {
                //returns all the records from table based on companyId in list format.
                return dataContext.CarModels.Where(query => query.CarCompanyId == companyId).Select(q => q.CarName).ToList();
            }
        }
    }
}

This class holds two methods. The GetCompanyListFromDB() method fetches the CarCompany list from DB. The GetCarsByCompanyId() method fetched the CarModel List based on CarCompanyId supplied.


ViewModel :



using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using CascadingDropdowns.Models;

namespace CascadingDropdowns.ViewModel
{
    //This object of this model is passed as parameter to view.
    public class CarViewModel
    {
        //List to hold the company names which is passed as model property.
        //This list is used to populate the first dropdown.
        public List<SelectListItem> listCarCompany { get; set; }
    }
}

View :


@model CascadingDropdowns.ViewModel.CarViewModel
@{
    Layout = "../Shared/_Layout.cshtml";
}


<div>
@Html.DropDownListFor(model => model.listCarCompany, Model.listCarCompany)
<select id="Cars" style="width:100px;">
</select>
</div>

<script type="text/javascript">
    $("#listCarCompany").change(function () {
        var selectedValue = $(this).val();
        $.ajax({
            url: '@Url.Action("GetCarsBycompany", "Car")',
            type: 'POST',
            data: { "selectedValue": selectedValue },
            dataType: 'json',
            success: function (response) {
                var items = "";
                $.each(response.CarList, function (i, item) {
                    items += "<option value=\"" + item + "\">" + item + "</option>";
                });
                $("#Cars").html(items);
            },
            error: function (error) {
            }

        });
    });
</script>

We have used DropDownListFor helper to render the first dropdwon. We have binded the dropdown to model property "listCarCompany". We have created second dropdown  using select with id attribute as "Cars". When user will select value in First Dropdown, jQuery fetched the value of first dropdown. This value is posted as parameter to GetCarsBycompany method which returns the list of cars depending on the value passed. The json result is the binded to the second dropdown.


SnapShots :








18 comments:

  1. This is very informative article. Thanks for sharing with us. Below links a very helpful to complite my task.

    http://www.mindstick.com/Articles/65decad5-92c7-4bfc-bfb5-22b04bf6a1ab/?Cascading%20Dropdown%20list%20in%20ASP%20Net%20MVC

    http://blogs.msdn.com/b/rickandy/archive/2012/01/09/cascasding-dropdownlist-in-asp-net-mvc.aspx

    ReplyDelete
  2. thank you for posting cascading dropdown list post

    ReplyDelete
  3. Replies
    1. plz I have a question .. where to put the class CarViewModel

      Delete
    2. Create a new Folder under solution, name it as ViewModels and then create a class with name CarViewModel.

      OR you can check out the video link.

      Delete
    3. is there anything else i have to add to this project which is not mentioned in this tuto, because i've done all the steps, and it doesn't work for me ?

      Delete
    4. The above tutorial information is enough.
      What are you stuck ? can you explain in brief, or are you getting any error ?

      Delete
  4. No i'm not getting any error :( but it doesn't work

    ReplyDelete
  5. Send me your code at 20fingers2brains@gmail.com.

    ReplyDelete
  6. Thank you very much for this post! The comments in the code were very helpful to understand what's going on. Even though this was written using MVC 3, it works with VS 2013, MVC 5 and EF 6 just fine. The only change I had to make was to add two lines in the view to load jQuery.

    ReplyDelete
  7. Thank you very much for this post, it's very helpful, I used it to know how to populate my Dropdownlist from DB, but I have an exception: "The object reference is not set to an instance of an object" in this place in the view :
    @Html.DropDownListFor(model => model.TypeCotisant,Model.TypeCotisant)
    can you help me please

    ReplyDelete
  8. Thank you for the article. This is very helpful.

    I was able to get this to work successfully, however I have one question. The second drop-down does properly change to the correct selection based on the first drop-down but when I go back and choose the word "Select" in the first drop-down, the second field maintains the previous list. It does not clear out.

    How can I clear the second drop-down field when I select the word "Select" again in the first drop-down field?

    ReplyDelete
  9. Add a check inside change event call of first dropdown.
    if (selectedValue != "Select") {
    }
    and in the else part clear the dropdown.

    else {
    $("#Cars").empty();
    }

    ReplyDelete
  10. how to give validations using jquery

    ReplyDelete
  11. Can you please give me an example with 3 levels dropdown? Thank you

    ReplyDelete