In this article we will learn the Cascading Dropdown operation in Aurelia by fetching JSON data from Web API with ASP.NET Core MVC.
Introduction
Aurelia is a modern, open source client side JavaScript framework for web and mobile application development. Earlier we have seen how to Bind Dropdown in Aurelia. We have equally experienced how to Resolve CORS in Web API with ASP.NET Core 1.0 MVC. In this article, we will use those two concepts and extend our experiment for developing a cascading drop down in Aurelia by fetching JSON data from Web API with ASP.NET Core MVC.
Our output would look like this
Creating the WebAPI project
Fire up Visual Studio 2015 and then File -> New -> Project -> Web -> Asp.net Core Web Applications(.Net Core).Choose the target Framework as .Net Framework 4.6.1.
The next screen that pops up display's a list of templates and we need to choose Web API template.
ASP.NET Core 1.0 includes only Web API and MVC but not SignalR or Web Pages yet. We choose the Web API and Click "OK" button and here is our "Welcome Screen"
Create a Model Class
Now let us first create a folder by the name "Model". Then add Country,State and City models as under
namespace WebAPI_Asp.netCore.Model
{
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; }
}
}
Our Country model is a simple Country Class which has some scalar properties like CountryID,CountryName This Country model represents the Country related data model in our application. The State Class has three properties viz. StateID,StateName and CountryID. It represents the State related data model in our application. The City Class has three properties viz. CityID,CityName and StateID. It represents the City related data model in our application.
Create the Repository objects
The repository objects are responsible for encapsulating the data layer. It contains logic for retrieving data and mapping it to an entity model.
Now let us first create a folder by the name "Repository" and first create an interface say IMasterRepository.cs inside that folder. This interface is responsible for fetching the Master data.
using System.Collections.Generic;
using WebAPI_Asp.netCore.Model;
namespace WebAPI_Asp.netCore.Repository
{
public interface IMasterRepository
{
List<Country> GetCountries();
List<State> GetStates(int countryID);
List<City> GetCities(int stateID);
}
}
Next we need to have a concrete repository class which will implement the IMasterRepository interface. Let us add MasterRepository.cs class that will implement the IMasterRepository and will provide the concrete implementation for the same.
using System.Collections.Generic;
using System.Linq;
using WebAPI_Asp.netCore.Model;
namespace WebAPI_Asp.netCore.Repository
{
public class MasterRepository : IMasterRepository
{
public List<Country> GetCountries()
{
return new List<Country>()
{
new Country() { CountryID =1, CountryName="India" },
new Country() { CountryID =2, CountryName="Nigeria" }
};
}
public List<State> GetStates(int countryID)
{
return new List<State>()
{
new State() { StateID =1, StateName="Karnataka", CountryID =1 },
new State() { StateID =2, StateName="WestBengal", CountryID =1 },
new State() { StateID =3, StateName="Borno", CountryID =2 },
new State() { StateID =4, StateName="Cross River", CountryID =2 }
}.Where(w=>w.CountryID == countryID).ToList() ;
}
public List<City> GetCities(int stateID)
{
return new List<City>()
{
new City() { CityID =1, CityName="Bangalore", StateID =1 },
new City() { CityID =2, CityName="Mysore", StateID =1 },
new City() { CityID =3, CityName="Kolkata", StateID =2 },
new City() { CityID =4, CityName="Bakhali", StateID =2 },
new City() { CityID =5, CityName="Kukawa", StateID =3 },
new City() { CityID =6, CityName="Damasak", StateID =3 },
new City() { CityID =7, CityName="Calabar", StateID =4 },
new City() { CityID =8, CityName="Ugep", StateID =4 }
}.Where(w => w.StateID == stateID).ToList();
}
}
}
The MasterRepository is a concrete implementation. In the GetCountries() method, we fetch the Country Records. The GetStates(int countryID)() funciton, accepts a countryID and fetch the corresponding State Records.The GetCities(int stateID)() funciton, accepts a stateID and fetch the corresponding City Records.
Register the repository to the ASP.NET Core's dependency injection and Activate CORS
Earlier we have seen how to resolve CORS in Web API with ASP.NET Core 1.0 MVC and how to add dependency in WebAPI with ASP.NET Core MVC using inbuilt DI container. The Startup.cs file looks as under
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using WebAPI_Asp.netCore.Repository;
namespace WebAPI_Asp.netCore
{
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
services.AddSingleton<IMasterRepository, MasterRepository>();
//Add the CORS services
services.AddCors();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseCors(builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
app.UseMvc();
}
}
}
Now expand the Controllers folder and create MasterController.cs and add the following code
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using WebAPI_Asp.netCore.Model;
using WebAPI_Asp.netCore.Repository;
namespace WebAPI_Asp.netCore.Controllers
{
[Route("MasterRecords")]
public class MasterController : Controller
{
public MasterController(IMasterRepository masters)
{
MasterRecords = masters;
}
public IMasterRepository MasterRecords { get; set; }
[HttpGet]
[Route("GetCountries")]
public List<Country> GetCountries()
{
return MasterRecords.GetCountries();
}
[HttpGet]
[Route("GetStates")]
public List<State> GetStates(int countryID)
{
return MasterRecords.GetStates(countryID);
}
[HttpGet]
[Route("GetCities")]
public List<City> GetCities(int stateID)
{
return MasterRecords.GetCities(stateID);
}
}
}
Now we can test the API Services of the MasterController.cs through PostMan.
For fetching the countries
For fetching the states
For fetching the cities
So, it's all working.
Building the Aurelia Interface
Create a folder say AureliaExperiment at your favorite location.
Then download the basic Aurelia project setup zipped file from here.
Extract the Zipped file and copy it under AureliaExperiment folder. It looks as under
Now we will design the template in "app.html"
app.html
----------
<template>
<h2><font color="green">Cascading DropDown Example in Aurelia</font></h2>
<select change.delegate="fetchStates()" value.bind="selectedCountryId">
<option value="">-Choose Country-</option>
<option value="${country.countryID}"
repeat.for="country of Countries">${country.countryName}</option>
</select>
<p>Selected Country Id: ${selectedCountryId}</p>
<select change.delegate="fetchCities()" value.bind="selectedStateId">
<option value="">-Choose State-</option>
<option value="${state.stateID}"
repeat.for="state of States">${state.stateName}</option>
</select>
<p>Selected State Id: ${selectedStateId}</p>
<select value.bind="selectedCityId">
<option value="">-Choose City-</option>
<option value="${city.cityID}"
repeat.for="city of Cities">${city.cityName}</option>
</select>
<p>Selected City Id: ${selectedCityId}</p>
</template>
The purpose of Repeat.for is to iterate over objects. After we iterate the Countries array, we have bind the ${country.CountryID} property as the ID field of the Dropdown and display ${country.CountryName} property as the value. When the country dropdown changes, we are picking up the selectedCountryId property and passed to the Web API for fetching the records for the State. When the state dropdown changes, we are picking up the selectedStateId property and passed to the Web API for fetching the records for the City.
Now for fetching the records from the Web API, let's write the below code in "app.js" file
import 'fetch';
import {HttpClient} from 'aurelia-fetch-client';
let httpClient = new HttpClient();
export class App {
constructor() {
this.Countries = null;
this.selectedCountryId= null;
this.States = null;
this.selectedStateId= null;
this.Cities = null;
this.selectedCityId= null;
this.fetchCountries();
}
fetchCountries()
{
httpClient.fetch('http://localhost:7625/MasterRecords/GetCountries')
.then(response => response.json())
.then(data => {
this.Countries = data;
});
}
fetchStates()
{
var currentCountryID = this.selectedCountryId;
httpClient.fetch('http://localhost:7625/MasterRecords/GetStates?countryID=' + currentCountryID )
.then(response => response.json())
.then(data => {
this.States = data;
});
}
fetchCities()
{
var currentStateID = this.selectedStateId;
httpClient.fetch('http://localhost:7625/MasterRecords/GetCities?stateID=' + currentStateID )
.then(response => response.json())
.then(data => {
this.Cities = data;
});
}
}
Earlier we have talked about how to use Aurelia-fetch-client for a HTTP GET Request. We have used Aurelia-fetch-client in this case for fetching the records from the Web API and bind them to the respective properties.
Now it's time for testing. On the initial page load it appears as under
Now choose "Nigeria" and then it appears as
Now choose "Cross River" from the State Dropdown and then it appears as
Now choose "Calabar" from the City Drop down and the final result is
Reference
Binding: Basics
Conclusion
In this article we have learnt the Cascading Drop down operation in Aurelia by fetching JSON data from Web API with ASP.NET Core MVC. Hope this will be useful. Thanks for reading. Zipped file attached.