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 (.Net Core 8)
MVC.
The
Cascading i.e. dependent
Country,
State and
City DropDownLists will be populated from database using
jQuery AJAX in
ASP.Net Core (.Net Core 8)
MVC.
Database
I have made use of the following table Countries, States and Cities with the schema as follows.
Countries Table
States Table
Cities Table
Note: You can download the database table SQL by clicking the download link below.
Configuring the Anti-Forgery Token and JSON Serializer setting
The
first step is to configure
JSON Serializer settings in the
Program.cs file.
1. Open the Program.cs class from the Solution Explorer window.
2. Inherit the following namespace.
using Newtonsoft.Json.Serialization;
3. Then inside the
AddJsonOptions method, you will have to add the following code which will instruct the program to use
Newtonsoft library for
JSON serialization.
var builder = WebApplication.CreateBuilder(args);
//Enabling MVC
builder.Services.AddControllersWithViews()
.AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
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.
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 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.
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 HomeController : 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
HTML Markup
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 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/3.7.1/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
Browser Compatibility
* All browser logos displayed above are property of their respective owners.
Downloads