Today, in this article, I will explain how to perform Cascading dropdown list using MVC, Web API, and AngularJS. Here, I am using three tables: Country, State, and City respectively. If we select a country, it should display country-related states and when we select a state, then it should display state-related cities. Finally, here, we will use MVC, Web, AngularJS, and SQL Server. I have completed the same already using jQuery. You can find the article at this link. So now, let us see step by step.
Step 1
We have to create three tables: Country, State, and City.
Step 2
Now, we will create an MVC application but we create two projects here -- Web API project to create service, and MVC Project for consuming the service. So now, we will add the first MVC project and then we will add Web API Project.
Just go through File->New ->Web application ->select MVC ->OK.
Step 3
Now, let us add tables in Web API project using Entity framework. So for this, go to Model folder -> Right click -> Add -> New item -> ADO.NET Entity Data Model -> click Add -> select database first approach->Click Next.
Select New Connection and give the connection details, then select database ->Click OK.
Choose tables and click OK.
Step 4
Now we write the logic for bind Country, State and City. So I create a folder, Business Logic, and take a class CascadingLogic.cs, and write the logic:
- public class CascadingLogic
- {
- JobPortalEntities dbEntity = new JobPortalEntities();
-
- public List<Country> BindCountry()
- {
- this.dbEntity.Configuration.ProxyCreationEnabled = false;
-
- List<Country> lstCountry = new List<Country>();
- try
- {
- lstCountry = dbEntity.Countries.ToList();
- }
- catch (Exception ex)
- {
- ex.ToString();
- }
- return lstCountry;
- }
-
- public List<State> BindState(int countryId)
- {
- List<State> lstState = new List<State>();
- try
- {
- this.dbEntity.Configuration.ProxyCreationEnabled = false;
-
- lstState = dbEntity.States.Where(a => a.CountryId == countryId).ToList();
- }
- catch (Exception ex)
- {
- ex.ToString();
- }
- return lstState;
- }
-
- public List<City> BindCity(int stateId)
- {
- List<City> lstCity = new List<City>();
- try
- {
- this.dbEntity.Configuration.ProxyCreationEnabled = false;
-
- lstCity = dbEntity.Cities.Where(a => a.StateId == stateId).ToList();
- }
- catch (Exception ex)
- {
- ex.ToString();
- }
- return lstCity;
- }
- }
After that, we will add an API Controller.
Create an API method and call the methods one by one.
- [RoutePrefix("api/Cascading")]
- public class CascadingDetailsController : ApiController
- {
- CascadingLogic objCasc = new CascadingLogic();
- [HttpGet]
- [Route("CountryDetails")]
- public List<Country> BindCountryDetails()
- {
-
-
- List<Country> countryDetail = new List<Country>();
- try
- {
- countryDetail = objCasc.BindCountry();
- }
- catch (ApplicationException ex)
- {
- throw new HttpResponseException(new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest, ReasonPhrase = ex.Message });
- }
- catch (Exception ex)
- {
- throw new HttpResponseException(new HttpResponseMessage { StatusCode = HttpStatusCode.BadGateway, ReasonPhrase = ex.Message });
- }
-
- return countryDetail;
- }
-
- [HttpGet]
- [Route("StateDetails")]
- public List<State> BindStateDetails(int CountryId)
- {
-
- List<State> stateDetail = new List<State>();
- try
- {
- stateDetail = objCasc.BindState(CountryId);
- }
- catch (ApplicationException ex)
- {
- throw new HttpResponseException(new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest, ReasonPhrase = ex.Message });
- }
- catch (Exception ex)
- {
- throw new HttpResponseException(new HttpResponseMessage { StatusCode = HttpStatusCode.BadGateway, ReasonPhrase = ex.Message });
- }
-
- return stateDetail;
- }
-
- [HttpGet]
- [Route("CityDetails")]
- public List<City> BindCityDetails(int stateId)
- {
- List<City> cityDetail = new List<City>();
- try
- {
- cityDetail = objCasc.BindCity(stateId);
- }
- catch (ApplicationException ex)
- {
- throw new HttpResponseException(new HttpResponseMessage { StatusCode = HttpStatusCode.BadRequest, ReasonPhrase = ex.Message });
- }
- catch (Exception ex)
- {
- throw new HttpResponseException(new HttpResponseMessage { StatusCode = HttpStatusCode.BadGateway, ReasonPhrase = ex.Message });
- }
-
- return cityDetail;
- }
-
- }
Step 5
Now, let us go to MVC project and add a Controller.
After that, create an action method for View and View page.
- public ActionResult Details()
- {
- return View();
- }
NOTE
Here, we will not consume the API service using server-side but directly use the client-side.
Step 6
Here, we will use Angular js for consuming the service of Country, State and City. So for that, first we have to download AngularJS library. We have downloaded the same using NuGet Package Manager.
After that, we added three JavaScript files - App.js for registering the module; Service.js for writing the factory method; and Cascad.js file for writing the Controller code.
In App.js, write the below code.
- var app = angular.module('MyApp', []);
In Service.js, write the below code.
- app.factory('CommonUrlService', function ($http) {
- var fac = {};
-
-
- fac.GetCountry = function () {
- return $http.get('http://localhost:54188/api/Cascading/CountryDetails');
- };
-
-
- fac.GetState = function (CountryId) {
- return $http.get('http://localhost:54188/api/Cascading/StateDetails/' + CountryId);
- };
-
-
- fac.GetCity = function (stateId) {
- return $http.get('http://localhost:54188/api/Cascading/CityDetails/' + stateId);
- };
-
- return fac;
- });
Then, in Cascad.js file, write the below code.
- app.controller('CascadController', function ($scope, CommonUrlService) {
-
- $scope.CountryList = {};
-
- $scope.CityList = {};
- $scope.StateList = {};
-
- $scope.CountryText = "Select Country..";
-
- CommonUrlService.GetCountry().then(function (d) {
-
- $scope.CountryList = d.data;
- });
-
- $scope.GetState = function () {
-
- $scope.StateText = "Please Wait...";
- CommonUrlService.GetState($scope.CountryId).then(function (d) {
- $scope.StateList = d.data;
- $scope.StateText = "Select State";
- }, function (error) {
- alert('Error!');
- });
- }
-
- $scope.GetCity = function () {
- $scope.CityText = "Please Wait...";
-
- CommonUrlService.GetCity($scope.StateId).then(function (d) {
- $scope.CityList = d.data;
- $scope.CityText = "Select City";
- }, function (error) {
- alert('Error!');
- });
- }
-
- });
Okay! Custom Angular logic is completed now. We have to design the HTML of the View page now.
And register the ng-app directory and ng-controller directory.
- <script src="~/Scripts/angular.js"></script>
- <script src="~/Scripts/Angulajs/App.js"></script>
- <script src="~/Scripts/Angulajs/Cascad.js"></script>
- <script src="~/Scripts/Angulajs/Service.js"></script>
-
-
- <h1>Cascading Dropdown List of Country, State and City</h1>
- <hr />
- <br />
- <div class="row" ng-app="MyApp">
- <div class="col-lg-3"></div>
- <div class="col-lg-6" ng-controller="CascadController">
-
- <div class="form-group">
- <label class="col-md-4 control-label">Country Name</label>
- <div class="col-md-6">
- <select class="form-control" id="ddlCountry" ng-model="CountryId" ng-options="C.CountryId as C.CountryName for C in CountryList" ng-change="GetState()">
- <option value="{{CountryText}}">Select Country</option>
- </select><br />
- </div>
- </div>
-
- <div class="form-group">
- <label class="col-md-4 control-label">State Name</label>
- <div class="col-md-6">
- <select class="form-control" id="ddlState" ng-model="StateId" ng-options="S.StateId as S.StateName for S in StateList" ng-change="GetCity()">
- <option>{{StateText}}</option>
- </select>
- <br />
-
- </div>
- </div>
- <br />
- <div class="form-group">
- <label class="col-md-4 control-label">City Name</label>
- <div class="col-md-6">
- <select class="form-control" id="ddlCity" ng-model="CityId" ng-options="C.CityId as C.CityName for C in CityList">
- <option>{{CityText}}</option>
- </select>
-
- </div>
- </div>
- </div>
- <div class="col-lg-3"></div>
- </div>
Output Design
Run the project, however, we have to run both projects at one time so for this, so we have to set some changes. Right-click on the solution project and go to properties. Here, check the Multiple Startup Projects option and click the Apply button.
Now, we see an output with an unexpected error.
This error is called CORS. So first, we have to know what CORS is and how to resolve this problem.
According to Wikipedia,
Cross-origin resource sharing (CORS) is a mechanism that allows restricted resources (e.g. fonts) on a web page to be requested from another domain outside the domain from which the first resource was served.
For more details, click this
link.
Now, let us learn how to resolve this problem.
So for this, we have to download CORS in Web API project. Go to NuGet Package Manager and download the following file.
After that, goto App_Start folder in Web API project and then WebApiConfig.cs class. Here, modify the Register method with the below code.
- var cors = new EnableCorsAttribute("*", "*", "*");
- config.EnableCors(cors);
Now, save changes and run the project to see the final output.
Select a country
Select a state
Thanks! I hope this article was helpful.