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
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 Startup.cs file.
1. Open the Startup.cs class from the Solution Explorer window.
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());
}
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 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.
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
Downloads