asp.net mvc cascading dropdownlist Edit

Murugan Andezuthu Dharmaratnam | 11 September 2020 | 41

In a web application, there are forms that require a cascading drop-down. The most common example would be a form where you have to fill in the address with a city, state, country. When you select the Country, state drop-down is populated using an ajax request, When u select a state all the city's of that state appear in the dropdown.

Check the below sample code which does the same. I am hard coding the data for city-state and country for this example. You can modify the code to get the data from a database.

You should start by creating a new asp .net MVC application. Let's create a class that would provide the data for city, state & country. Please check the sample code below.

Application Data

right-click on the model folder and create a class called Address. copy-paste the code below. I have put all the classes in the same class. Ideally, you should have all the classes in separate files.

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

namespace CascadingDropdown.Models
{
    public class Address
    {
        public int Id { get; set; }
        public String Name { get; set; }
        public int CityId { get; set; }
        public int StateId { get; set; }
        public int CountryId { get; set; }
    }
    public class Country
    {
        public int Id { get; set; }
        public String Name { get; set; }

        public List Get()
        {
            List lstCountry = new List()
            {
                new Country() { Id = 91, Name="India" },
                new Country() { Id = 1, Name="USA" },
            };
            return lstCountry;
        }
    }
    public class State
    {
        public int Id { get; set; }
        public int CountryId { get; set; }
        public String Name { get; set; }
        public List Get(int Id)
        {
            List lstState = new List()
            {
                new State() { Id = 1, CountryId = 91, Name="Kerala" },
                new State() { Id = 2, CountryId = 91, Name="Karnatake" },
                new State() { Id = 3, CountryId = 1, Name="Michigan" },
                new State() { Id = 4, CountryId = 1, Name="New York" },
            };
            return lstState.Where(x => x.CountryId == Id).ToList();
        }
    }
    public class City
    {
        public int Id { get; set; }
        public int StateId { get; set; }
        public String Name { get; set; }
        public List Get(int Id)
        {
            List lstCity = new List()
            {
                new City() { Id = 1, StateId = 1, Name="Ernakulam" },
                new City() { Id = 2, StateId = 1, Name="Alleppey" },
                new City() { Id = 3, StateId = 1, Name="Kottayam" },
                new City() { Id = 4, StateId = 2, Name="Bangalore" },
                new City() { Id = 5, StateId = 2, Name="Mysore" },
                new City() { Id = 6, StateId = 3, Name="Detroit" },
                new City() { Id = 7, StateId = 3, Name="Grand Rapids" },
                new City() { Id = 8, StateId = 4, Name="New York City" }
            };
            return lstCity.Where(x => x.StateId == Id).ToList();
        }
    }
}

Step 1: Add Address Controller

Right-click on the Controllers folder and select Add -> Controller. Select MVC 5 Controller with read/write actions. Name the controller AddressController.

Create the .cshtml view page by right-clicking on the Edit(int id) method and selecting Add View.
View Name should be Edit, Select the Edit Template & Select Address Model for the Model class.

Step 2: Modify Edit(int id) method to pass data to view

public ActionResult Edit(int id)
{
    Address retval = new Address();

    List<Country> lstCountry = new Country().Get();
    lstCountry.Insert(0, new Country() { Name = "Select Country", Id = 0 });
    ViewBag.CountryId = new SelectList(lstCountry, "Id", "Name", retval.Id);

    List<State> lstState = new List<State>();
    lstState.Insert(0, new State() { Name = "Select State", Id = 0 });
    ViewBag.StateId = new SelectList(lstState, "Id", "Name", retval.Id);

    List<City> lstCity = new List<City>();
    lstCity.Insert(0, new City() { Name = "Select City", Id = 0 });
    ViewBag.CityId = new SelectList(lstCity, "Id", "Name", retval.Id);

    return View(retval);
}     

ViewBag is used to move the list of country to the view

Step 3: Modify the view to display drop down

we will modify the cshtml code to display drop-down instead of the text element. we will replicate this line of code with

@Html.EditorFor(model => model.CountryId, new { htmlAttributes = new { @class = "form-control" } })

with

@Html.DropDownList("CountryId", null, htmlAttributes: new { @class = "form-control" })

Modified Code

<div class="form-group">
    @Html.LabelFor(model => model.CountryId, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.DropDownList("CountryId", null, htmlAttributes: new { @class = "form-control" })
        @Html.ValidationMessageFor(model => model.CountryId, "", new { @class = "text-danger" })
    </div>
</div>

<div class="form-group">
    @Html.LabelFor(model => model.StateId, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.DropDownList("StateId", null, htmlAttributes: new { @class = "form-control" })
        @Html.ValidationMessageFor(model => model.StateId, "", new { @class = "text-danger" })
    </div>
</div>

<div class="form-group">
    @Html.LabelFor(model => model.CityId, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.DropDownList("CityId", null, htmlAttributes: new { @class = "form-control" })
        @Html.ValidationMessageFor(model => model.CityId, "", new { @class = "text-danger" })
    </div>
</div>

Step 4: Add Methods GetState & GetCity

You have to add two methods GetState & GetCity to the controller to return json to view

public ActionResult GetState(int CountryId)
{
    List<State> lstState = new State().Get(CountryId);
    lstState.Insert(0, new State() { Name = "Select State", Id = 0 });
    return Json(lstState, JsonRequestBehavior.AllowGet);
}

public ActionResult GetCity(int StateId)
{
    List<City> lstCity = new City().Get(StateId);
    lstCity.Insert(0, new City() { Name = "Select City", Id = 0 });
    return Json(lstCity, JsonRequestBehavior.AllowGet);
}

Step 5: Call the Jquery method when Country & State selection changes.

The final step is to write javascript code which will be called when the user selects a country or state from the drop-down. This will make an ajax call to the server which will return the filtered data. The below script has to be added to the bottom of edit.cshtml page.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">

    $("#CountryId").change(function () {
        $("#StateId option").remove()
        var url = "/Address/GetState/?CountryId="   $("#CountryId").val();
        $.getJSON(url, function (data) {
            $.each(data, function (key, val) {
                var ele = $('<option value="'   val.Id   '">'   val.Name   '</option>');
                $("#StateId").append(ele);
            });
        });
    });


    $("#StateId").change(function () {
        $("#CityId option").remove()
        var url = "/Address/GetCity/?StateId="   $("#StateId").val();
        $.getJSON(url, function (data) {
            $.each(data, function (key, val) {
                var ele = $('<option value="'   val.Id   '">'   val.Name   '</option>');
                $("#CityId").append(ele);
            });
        });
    });


</script>


The javascript function is called when the user selects a country or state from the drop-down. On selection change, the javascript makes a call to the controller which returns the filtered data in json format. Javascript is used to bind the JSON data to state and city dropdown.

Output