In this article I will explain with an example, how to populate Cascading i.e. dependent Country, State and City DropDownLists using jQuery AJAX in ASP.Net Core MVC.
The Cascading i.e. dependent Country, State and City DropDownLists will be populated from database using jQuery AJAX in ASP.Net Core MVC.
 
 
Database
For this example I have used the following three tables Countries, States and Cities with the schema as follow.
Countries Table
ASP.Net Core MVC: Cascading (Dependent) Country State City DropDownLists using jQuery AJAX
 
States Table
ASP.Net Core MVC: Cascading (Dependent) Country State City DropDownLists using jQuery AJAX
 
Cities Table
ASP.Net Core MVC: Cascading (Dependent) Country State City DropDownLists using jQuery AJAX
 
Note: You can download the database table SQL by clicking the download link below.
          Download SQL file
 
 
Configuring the Anti-Forgery Token and JSON Serializer setting
The first step is to configure JSON Serializer settings in the Startup.cs file.
1. Open the Startup.cs class from the Solution Explorer window.
ASP.Net Core MVC: Cascading (Dependent) Country State City DropDownLists using jQuery AJAX
 
2. Add the following namespaces.
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Serialization;
 
3. Then inside the ConfigureServices method, you will have to add the following code which will instruct the program to use Newtonsoft library for JSON serialization.
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
            .AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
}
 
For more details, regarding how to configure JSON Serializer setting in ASP.Net Core MVC, please refer my article ASP.Net Core: jQuery AJAX and JSON Example in ASP.Net Core MVC.
 
 
Model
The following Model class consists of three Generic List Collection properties of SelectListItem class for holding the Country, State and City records.
The Model class also contains three Integer type properties for holding the selected Country, State and City values.
Below the class, there are three classes Country, State and City which will be used to connect to the database table using Entity Framework.
public class CascadingModel
{
    public CascadingModel()
    {
        this.Countries = new List<SelectListItem>();
        this.States = new List<SelectListItem>();
        this.Cities = new List<SelectListItem>();
    }
 
    public List<SelectListItem> Countries { get; set; }
    public List<SelectListItem> States { get; set; }
    public List<SelectListItem> Cities { get; set; }
 
    public int CountryId { get; set; }
    public int StateId { get; set; }
    public int CityId { get; set; }
}
 
 
Database Context
Once the Entity Framework is configured and connected to the database table, the Database Context will look as shown below.
Note: For beginners in ASP.Net Core and Entity Framework, please refer my ASP.Net Core: Simple Entity Framework Tutorial with example. It covers all the information needed for connecting and configuring Entity Framework with ASP.Net Core.
 
using Microsoft.EntityFrameworkCore;
 
namespace Cascading_DropDownList_MVC_Core
{
    public class DBCtx : DbContext
    {
        public DBCtx(DbContextOptions<DBCtx> options) : base(options)
        {
        }
 
        public DbSet<Country> Countries { get; set; }
        public DbSet<State> States { get; set; }
        public DbSet<City> Cities { get; set; }
    }
 
    public class Country
    {
        public int CountryId { get; set; }
        public string CountryName { get; set; }
    }
 
    public class State
    {
        public int StateId { get; set; }
        public string StateName { get; set; }
        public int CountryId { get; set; }
    }
 
    public class City
    {
        public int CityId { get; set; }
        public string CityName { get; set; }
        public int StateId { get; set; }
    }
}
 
 
Controller
The Controller consists of following three Action methods.
Action method for handling GET operation
Inside this Action method, the records from Countries table is fetched using Entity Framework and then a Generic List collection of SelectListItem class objects is generated.
The generated Generic List collection of SelectListItem is assigned to the Countries property of the Model class object which is then returned back to the View.
 
Action method for handling AJAX operation
This Action method handles the call made by the jQuery AJAX function in the View.
Note: The following Action method handles AJAX calls and hence the return type is set to JsonResult. For more details, please refer my article ASP.Net Core: Return JSON from Controller in ASP.Net Core MVC.
 
This Action method accepts type and value parameters and based on the type i.e. Country or State, the Generic List collection of States or Cities respectively are fetched from the database using Entity Framework and returned to View in JSON format.
 
Action method for handling POST operation
This Action method handles the call made from the POST function from the View and is executed when the Submit button is clicked.
When the Form is submitted, the posted values are captured in three variables one for each i.e. Country, State and City.
Using these values, the Countries, States and Cities are again populated using Entity Framework in the Model class object which is then returned back to the View.
public class Home Controller : Controller
{
    private DBCtx Context { get; }
    public HomeController(DBCtx _context)
    {
        this.Context = _context;
    }
 
    public IActionResult Index()
    {
        CascadingModel model = new CascadingModel();
        model.Countries = (from customer in this.Context.Countries
                          select new SelectListItem
                          {
                              Value = customer.CountryId.ToString(),
                              Text = customer.CountryName
                          }).ToList();
        return View(model);
    }
 
    [HttpPost]
    public JsonResult AjaxMethod(string type, int value)
    {
        CascadingModel model = new CascadingModel();
        switch (type)
        {
            case"ddlCountries":
                model.States = (from customer in this.Context.States
                                where customer.CountryId == value
                                select new SelectListItem
                                {
                                    Value = customer.StateId.ToString(),
                                    Text = customer.StateName
                                }).ToList();
                break;
            case "ddlStates":
                model.Cities = (from customer in this.Context.Cities
                                where customer.StateId == value
                                select new SelectListItem
                                {
                                    Value = customer.CityId.ToString(),
                                    Text = customer.CityName
                                }).ToList();
                break;
        }
        return Json(model);
    }
 
    [HttpPost]
    public ActionResult Index(int countryId, int stateId, int cityId)
    {
        CascadingModel model = new CascadingModel();
        model.Countries = (from customer in this.Context.Countries
                           select new SelectListItem
                           {
                               Value = customer.CountryId.ToString(),
                               Text = customer.CountryName
                           }).ToList();
 
        model.States = (from customer in this.Context.States
                        where customer.CountryId == countryId
                        select new SelectListItem
                        {
                            Value = customer.StateId.ToString(),
                            Text = customer.StateName
                        }).ToList();
 
        model.Cities = (from customer in this.Context.Cities
                        where customer.StateId == stateId
                        select new SelectListItem
                        {
                            Value = customer.CityId.ToString(),
                            Text = customer.CityName
                        }).ToList();
 
        return View(model);
    }
}
 
 
View
Inside the View, in the very first line the CascadingModel class is declared as Model for the View.
The View consists of an HTML Form which has been created using following ASP.Net Tag Helpers attributes.
asp-action – Name of the Action. In this case the name is Index.
asp-controller – Name of the Controller. In this case the name is Home.
method – It specifies the Form Method i.e. GET or POST. In this case it will be set to POST.
The Form consists of three HTML DropDownList elements (SELECT) and a Submit Button.
The Model properties have been assigned to the DropDownLists using the asp-items Tag Helpers attribute.
Each DropDownList has been assigned a jQuery OnChange event handler, when an item is selected in the DropDownList, an AJAX call is made to the AjaxMethod Action method and based on the type value, the appropriate DropDownList is populated inside the Success event handler from the JSON result.
When the Submit Button is clicked, the Form gets submitted and the selected Country, State and City values are sent to the Controller.
Finally, inside the jQuery document ready event handler, if all the three DropDownLists are populated then the selected values are displayed using JavaScript Alert Message Box.
@model Cascading_DropDownList_MVC_Core.Models.CascadingModel
@addTagHelper*, Microsoft.AspNetCore.Mvc.TagHelpers
 
@{
    Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <form method="post" asp-controller="Home" asp-action="Index">
        <select id ="ddlCountries" name="CountryId" asp-for="CountryId" asp-items="Model.Countries">
            <option value="">Please select</option>
        </select>
        <br/><br/>
        <select id="ddlStates" name="StateId" asp-for="StateId" asp-items="Model.States">
            <option value="">Please select</option>
        </select>
        <br/><br/>
        <select id ="ddlCities" name="CityId" asp-for="CityId" asp-items="Model.Cities">
            <option value="">Please select</option>
        </select>
        <br/><br/>
        <input type="submit" value="Submit" />
    </form>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    <script type="text/javascript">
        $(function () {
            $("select").each(function () {
                if ($(this).find("option").length <= 1) {
                    $(this).attr("disabled", "disabled");
                }
            });
 
            $("select").change(function () {
                var value = 0;
                if ($(this).val() != "") {
                    value = $(this).val();
                }
                var id = $(this).attr("id");
                $.ajax({
                    type: "POST",
                    url: "/Home/AjaxMethod",
                    data: { value: value, type: id },
                    success: function (response) {
                        switch (id) {
                            case "ddlCountries":
                                DisableDropDown("#ddlStates");
                                DisableDropDown("#ddlCities");
                                PopulateDropDown("#ddlStates", response.States);
                                break;
                            case "ddlStates":
                                DisableDropDown("#ddlCities");
                                PopulateDropDown("#ddlCities", response.Cities);
                                break;
                        }
                    },
                    failure: function (response) {
                        alert(response.responseText);
                    },
                    error: function (response) {
                        alert(response.responseText);
                    }
                });
            });
 
            if ($("#ddlCountries").val() != "" && $("#ddlStates").val() != "" && $("#ddlCities").val() != "") {
                var message = "Country: " + $("#ddlCountries option:selected").text();
                message += "\nState: " + $("#ddlStates option:selected").text();
                message += "\nCity: " + $("#ddlCities option:selected").text();
                alert(message);
            }
        });
 
        function DisableDropDown(dropDownId) {
            $(dropDownId).attr("disabled", "disabled");
            $(dropDownId).empty().append('<option selected="selected" value="0">Please select</option>');
        }
 
        function PopulateDropDown(dropDownId, list) {
            if (list != null && list.length > 0) {
                $(dropDownId).removeAttr("disabled");
                $.each(list, function () {
                    $(dropDownId).append($("<option></option>").val(this['Value']).html(this['Text']));
                });
            }
        }
    </script>
</body>
</html>
 
 
Screenshot
ASP.Net Core MVC: Cascading (Dependent) Country State City DropDownLists using jQuery AJAX
 
 
Browser Compatibility
The above code has been tested in the following browsers.

Internet Explorer  FireFox  Chrome  Safari  Opera 

* All browser logos displayed above are property of their respective owners.

 
 
Downloads