Problem

I have a requirement to show a cascading dropdownlist based upon the selection of a different state. I am binding all the states of India with a state dropdownlist and on the change of the listed state, all the cities of that state will change and we can choose the city from the next dropdownlist. I need to do this entire operation using the Web API in the MVC.

Overview

In the ASP.Net MVC 5 project template there are various types of techniques by which we can do the database operations like Create, Read, Update and Delete (CRUD) in the web application. We can use the Entity Framework approaches in the controller using an Entity Data Model and display it from the View. We can create the service for doing data operations and using a service reference we can call the operations using JavaScript like Angular, Knockout or jQuery in the web application.

In the previous article Integrating ASP.Net Web API With MVC we have seen how to integrate the API with the MVC project template based an ASP.Net application and we have also done some operations like fetch the data from the database using the API call and using the MVC controller we call the API and return to the View. In this article we will add some more GET operations and display the cities based upon the states. We will fetch the data from the database using the API call and using the MVC controller we will call the API and return the data to the view.

Note

Please go through here before working with this article. This article is not the second part of the previous article. This is the extension part of the previous one.

Prerequisites

In this article the web applications are created with the new Project Templates like ASP.Net Web API 2 and ASP.Net MVC 5 in the Visual Studio 2013, so there are the following prerequisites before getting started:

Getting Started

Let's begin with the following sections:

Working with Database

In this section we will create the table of state and city and insert the state and city in the both tables. We will also create some Stored Procedures for fetching the data from both tables.

Step 1

Create the State and City tables and insert values into both of the tables.

State table

City Table Fields

Step 2

In the City table create the reference between City and State as shown in the following diagram.

City Table with Reference of State

Step 3

Create the Stored Procedure to select the state with the following code:

  1. Create Proc [dbo].[CT_State_Select]
  2. As
  3. Begin
  4. Set NOCOUNT ON
  5. Select State_ID, State_Name
  6. From State (NOLOCK)
  7. Order By State_Name ASC
  8. End

Step 4

Create the Stored Procedure to select the city with the following code:

  1. CREATE PROCEDURE [dbo].[CT_City_Select] (
  2. @StateId Int)
  3. AS
  4. BEGIN
  5. SET NOCOUNT ON
  6. SELECT
  7. City_ID, State_ID, City_Name
  8. FROM City (NOLOCK)
  9. WHERE State_ID=@StateId
  10. ORDER BY City_Name ASC
  11. END

Step 5

In the following code, we will update the previous Stored Procedure to fetch the College Details data:

  1. ALTER Proc [dbo].[CT_CollegeDetails_Select]
  2. As
  3. Begin
  4. Select
  5. c.CollegeID,
  6. c.[CollegeName],
  7. c.[CollegeAddress],
  8. c.[CollegePhone],
  9. c.[CollegeEmailID],
  10. c.[ContactPerson],
  11. c.[State],
  12. c.[City],
  13. s.State_Name,
  14. ci.City_Name
  15. From CollegeDetails c inner join State s on c.State = s.State_ID inner join City ci on c.City = ci.CIty_ID
  16. End

Creating Model

Since we have created the model in the previous application as said in the previous article, in this section we will add some more classes to add a new model. Start with the following procedure.

Step 1

Right-click on the "CollegeTrackerModels" project and add a new class as the named state with the following code:

  1. namespace CollegeTrackerModels
  2. {
  3. /// <summary>
  4. /// class for state
  5. /// </summary>
  6. public class State
  7. {
  8. #region Properties
  9. /// <summary>
  10. /// get and set the State ID
  11. /// </summary>
  12. public int State_ID { get; set; }
  13. /// <summary>
  14. /// get and set the State Name
  15. /// </summary>
  16. public string State_Name { get; set; }
  17. #endregion
  18. }
  19. }

Step 2

Add a new class as the named city with the following code:

  1. namespace CollegeTrackerModels
  2. {
  3. /// <summary>
  4. /// class for City
  5. /// </summary>
  6. public partial class City
  7. {
  8. #region Properties
  9. /// <summary>
  10. /// get and set the city id
  11. /// </summary>
  12. public int City_ID { get; set; }
  13. /// <summary>
  14. /// get and set the state id
  15. /// </summary>
  16. public int State_ID { get; set; }
  17. /// <summary>
  18. /// get and set the city name
  19. /// </summary>
  20. public string City_Name { get; set; }
  21. /// <summary>
  22. /// get and set the value
  23. /// </summary>
  24. public int Value { get; set; }
  25. /// <summary>
  26. /// get and set the text
  27. /// </summary>
  28. public string Text { get; set; }
  29. #endregion
  30. }
  31. }

Step 3

Update the CollegeDetails class with the following code:

  1. namespace CollegeTrackerModels
  2. {
  3. /// <summary>
  4. /// class for College Details
  5. /// </summary>
  6. public class CollegeDetails
  7. {
  8. #region Constructor
  9. public CollegeDetails()
  10. {
  11. this.States = new List<State>();
  12. this.Cities = new List<City>();
  13. }
  14. #endregion
  15. #region Properties
  16. ///<summary>
  17. ///get and set the College ID
  18. ///</summary>
  19. public int CollegeID { get; set; }
  20. ///<summary>
  21. ///get and set the College Name
  22. ///</summary>
  23. [Display(Name = "College Name")]
  24. public string CollegeName { get; set; }
  25. ///<summary>
  26. ///get and set the College Address
  27. ///</summary>
  28. [Display(Name = "College Address")]
  29. public string CollegeAddress { get; set; }
  30. ///<summary>
  31. ///get and set the College Phone
  32. ///</summary>
  33. [Display(Name = "College Phone")]
  34. public string CollegePhone { get; set; }
  35. ///<summary>
  36. ///get and set the College Email ID
  37. ///</summary>
  38. [Display(Name = "College EmailID")]
  39. public string CollegeEmailID { get; set; }
  40. ///<summary>
  41. ///get and set the Contact Person
  42. ///</summary>
  43. [Display(Name = "Contact Person")]
  44. public string ContactPerson { get; set; }
  45. ///<summary>
  46. ///get and set the State Id
  47. ///</summary>
  48. public Int16 StateId { get; set; }
  49. /// <summary>
  50. /// get and set the States
  51. /// </summary>
  52. public IList<State> States { get; set; }
  53. /// <summary>
  54. /// get and set the Cities
  55. /// </summary>
  56. public IList<City> Cities { get; set; }
  57. ///<summary>
  58. ///get and set the City Id
  59. ///</summary>
  60. public Int16 CityId { get; set; }
  61. ///<summary>
  62. ///get and set the status
  63. ///</sumary>
  64. public int Status { get; set; }
  65. /// <summary>
  66. /// get and set the state name
  67. /// </summary>
  68. [Display(Name="State")]
  69. public string State_Name { get; set; }
  70. /// <summary>
  71. /// get and set the city name
  72. /// </summary>
  73. [Display(Name="City")]
  74. public string City_Name { get; set; }
  75. #endregion
  76. }
  77. }

Working with Data Access Layer

In this section we will create some more classes to access the state and city table data.

Step 1

Right-click on the DAL folder and add a new class named "StateDAL" and provide the following code:

  1. using System;
  2. using System.Collections.Generic;
  3. using CollegeTrackerModels;
  4. using System.Configuration;
  5. using System.Data;
  6. using System.Data.SqlClient;
  7. namespace CollegeTrackerCore.DAL
  8. {
  9. public class StateDAL
  10. {
  11. #region Variables
  12. SqlConnection con;
  13. SqlCommand cmd;
  14. SqlDataAdapter adap;
  15. DataTable dt;
  16. DataSet ds;
  17. string connectionstring = ConfigurationManager.ConnectionStrings["CollegeTrackerConnectionString"].ConnectionString;
  18. #endregion
  19. #region Constructor
  20. public StateDAL()
  21. {
  22. con = new SqlConnection(this.connectionstring);
  23. }
  24. #endregion
  25. #region Public Method
  26. /// <summary>
  27. /// This method is used to get all State.
  28. /// </summary>
  29. /// <returns></returns>
  30. public List<State> GetState()
  31. {
  32. List<State> objState = new List<State>();
  33. using (cmd = new SqlCommand("CT_State_Select", con))
  34. {
  35. try
  36. {
  37. cmd.CommandType = CommandType.StoredProcedure;
  38. con.Open();
  39. adap = new SqlDataAdapter();
  40. adap.SelectCommand = cmd;
  41. dt = new DataTable();
  42. adap.Fill(dt);
  43. foreach (DataRow row in dt.Rows)
  44. {
  45. State state = new State();
  46. state.State_ID = Convert.ToInt32(row["State_ID"]);
  47. state.State_Name = row["State_Name"].ToString();
  48. objState.Add(state);
  49. }
  50. }
  51. catch (Exception ex)
  52. {
  53. con.Close();
  54. }
  55. return objState;
  56. }
  57. }
  58. #endregion
  59. }
  60. }

Step 2

Right-click on the DAL folder and add a new class named "CityDAL" and provide the following code:

  1. using System;
  2. using System.Collections.Generic;
  3. using CollegeTrackerModels;
  4. using System.Configuration;
  5. using System.Data;
  6. using System.Data.SqlClient;
  7. namespace CollegeTrackerCore.DAL
  8. {
  9. public class CityDAL
  10. {
  11. #region Variables
  12. SqlConnection con;
  13. SqlCommand cmd;
  14. SqlDataAdapter adap;
  15. DataTable dt;
  16. DataSet ds;
  17. string connectionstring = ConfigurationManager.ConnectionStrings["CollegeTrackerConnectionString"].ConnectionString;
  18. #endregion
  19. #region Constructor
  20. public CityDAL()
  21. {
  22. con = new SqlConnection(this.connectionstring);
  23. }
  24. #endregion
  25. #region Public Method
  26. /// <summary>
  27. /// This method is used to get all cities.
  28. /// </summary>
  29. /// <returns></returns>
  30. public List<City> GetCity(int stateId)
  31. {
  32. List<City> objCity = new List<City>();
  33. using (cmd = new SqlCommand("CT_City_Select", con))
  34. {
  35. cmd.CommandType = CommandType.StoredProcedure;
  36. dt = new DataTable();
  37. cmd.Parameters.AddWithValue("@StateId", stateId);
  38. adap = new SqlDataAdapter();
  39. adap.SelectCommand = cmd;
  40. try
  41. {
  42. con.Open();
  43. adap.Fill(dt);
  44. foreach (DataRow row in dt.Rows)
  45. {
  46. City city = new City();
  47. city.City_ID = Convert.ToInt32(row["City_ID"]);
  48. city.State_ID = Convert.ToInt32(row["State_ID"]);
  49. city.City_Name = row["City_Name"].ToString();
  50. objCity.Add(city);
  51. }
  52. }
  53. catch (Exception ex)
  54. {
  55. throw ex;
  56. }
  57. finally
  58. {
  59. con.Close();
  60. }
  61. return objCity;
  62. }
  63. }
  64. #endregion
  65. }
  66. }

Step 3

Update the "CollegeDAL" method named "GetAllCollegeDetails()" with the following code:

  1. public List<CollegeDetails> GetAllCollegeDetails()
  2. {
  3. List<CollegeDetails> objCollegeDetails = new List<CollegeDetails>();
  4. using (cmd = new SqlCommand("CT_CollegeDetails_Select", con))
  5. {
  6. try
  7. {
  8. cmd.CommandType = CommandType.StoredProcedure;
  9. con.Open();
  10. adap = new SqlDataAdapter();
  11. adap.SelectCommand = cmd;
  12. dt = new DataTable();
  13. adap.Fill(dt);
  14. foreach (DataRow row in dt.Rows)
  15. {
  16. CollegeDetails col = new CollegeDetails();
  17. col.CollegeID = Convert.ToInt32(row["CollegeID"]);
  18. col.CollegeName = row["CollegeName"].ToString();
  19. col.CollegeAddress = row["CollegeAddress"].ToString();
  20. col.CollegePhone = row["CollegePhone"].ToString();
  21. col.CollegeEmailID = row["CollegeEmailID"].ToString();
  22. col.ContactPerson = row["ContactPerson"].ToString();
  23. col.State_Name = row["State_Name"].ToString();
  24. col.City_Name = row["City_Name"].ToString();
  25. objCollegeDetails.Add(col);
  26. }
  27. }
  28. catch (Exception ex)
  29. {
  30. con.Close();
  31. }
  32. return objCollegeDetails;
  33. }
  34. }

Step 4

Add new classes named "StateBLCore" and "CityBLCore" in the BLL folder. Begin with following procedure.

Working with API Project

In this section we will add ome more classes to access the data layer. Start with the following procedure:

Step 1

In the "CollegeTrackerAPI" project go to the Areas folder and right-click on the BLL folder to add two more classes named "CityBL" and "StateBL". Replace the code with the following code:

  1. using CollegeTrackerCore.BLL;
  2. using CollegeTrackerModels;
  3. using System.Collections.Generic;
  4. namespace CollegeTrackerAPI.Areas.BLL
  5. {
  6. internal sealed class CityBL : CityBLCore
  7. {
  8. /// <summary>
  9. /// This method is used to get the CityDetails
  10. /// </summary>
  11. /// <return></return>
  12. internal new List<City> GetCity(int stateId)
  13. {
  14. return base.GetCity(stateId);
  15. }
  16. }
  17. }

  1. using CollegeTrackerCore.BLL;
  2. using CollegeTrackerModels;
  3. using System.Collections.Generic;
  4. namespace CollegeTrackerAPI.Areas.BLL
  5. {
  6. internal sealed class StateBL : StateBLCore
  7. {
  8. /// <summary>
  9. /// This method is used to get the states
  10. /// </summary>
  11. /// <return></return>
  12. internal new List<State> GetState()
  13. {
  14. return base.GetState();
  15. }
  16. }
  17. }

Step 2

Go to the Controllers folder and add a new Web API 2 Controller named "StateDetails". Replace the code with the following code:

  1. using CollegeTrackerAPI.Areas.BLL;
  2. using CollegeTrackerModels;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Net;
  6. using System.Net.Http;
  7. using System.Web.Http;
  8. namespace CollegeTrackerAPI.Areas.Controller
  9. {
  10. public class StateDetailsController : ApiController
  11. {
  12. #region variable
  13. ///<summary>
  14. ///variable for StateBL
  15. ///</summary>
  16. private StateBL objStateBL;
  17. ///<summary>
  18. /// variable for httpResponseMessage
  19. /// </summary>
  20. HttpResponseMessage response;
  21. # endregion
  22. #region Response Method
  23. ///summary
  24. /// This method is used to fetch StateDetails
  25. /// <summary>
  26. /// <return></return>
  27. [HttpGet, ActionName("GetAllStateDetails")]
  28. public HttpResponseMessage GetAllStatesDetails()
  29. {
  30. objStateBL = new StateBL();
  31. HttpResponseMessage response;
  32. try
  33. {
  34. var detailsResponse = objStateBL.GetState();
  35. if (detailsResponse != null)
  36. response = Request.CreateResponse<List<State>>(HttpStatusCode.OK, detailsResponse);
  37. else
  38. response = new HttpResponseMessage(HttpStatusCode.NotFound);
  39. }
  40. catch (Exception ex)
  41. {
  42. response = Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message);
  43. }
  44. return response;
  45. }
  46. #endregion
  47. }
  48. }

Step 3

Add a new Controller named "CityDetails" and add the following code:

  1. using CollegeTrackerAPI.Areas.BLL;
  2. using CollegeTrackerModels;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Net;
  6. using System.Net.Http;
  7. using System.Web.Http;
  8. namespace CollegeTrackerAPI.Areas.Controller
  9. {
  10. public class CityDetailsController : ApiController
  11. {
  12. #region variable
  13. ///<summary>
  14. ///variable for CityBL
  15. ///</summary>
  16. private CityBL objCityBL;
  17. ///<summary>
  18. /// variable for httpResponseMessage
  19. /// </summary>
  20. HttpResponseMessage response;
  21. #endregion
  22. #region Response Method
  23. ///summary
  24. /// This method is used to fetch CityDetails
  25. /// <summary>
  26. /// <return></return>
  27. [HttpGet, ActionName("GetAllCityDetails")]
  28. public HttpResponseMessage GetAllCityDetails(int stateId)
  29. {
  30. objCityBL = new CityBL();
  31. HttpResponseMessage response;
  32. try
  33. {
  34. var detailsResponse = objCityBL.GetCity(stateId);
  35. if (detailsResponse != null)
  36. response = Request.CreateResponse<List<City>>(HttpStatusCode.OK, detailsResponse);
  37. else
  38. response = new HttpResponseMessage(HttpStatusCode.NotFound);
  39. }
  40. catch (Exception ex)
  41. {
  42. response = Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message);
  43. }
  44. return response;
  45. }
  46. #endregion
  47. }
  48. }

Working with User Interface Layer

In this section we will update the controller and add some new views to create the new view and display the dropdownlist in the view. Use the following procedure.

Step 1

Update the "CollegeDetails" controller and add the following code to it:

  1. public ActionResult CreateCollegeDetails()
  2. {
  3. CollegeDetails objcollege = new CollegeDetails();
  4. objcollege.States = GetAllStates();
  5. return View("~/Views/CollegeDetails/CreateCollegeDetails.cshtml", objcollege);
  6. }
  7. public List<State> GetAllStates()
  8. {
  9. var list = new List<CollegeTrackerModels.State>();
  10. var httpClient = new HttpClient();
  11. httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
  12. HttpResponseMessage response;
  13. response = httpClient.GetAsync("http://localhost:59866/api/" + "StateDetails/GetAllStateDetails/").Result;
  14. response.EnsureSuccessStatusCode();
  15. List<State> stateList = response.Content.ReadAsAsync<List<State>>().Result;
  16. if (!object.Equals(stateList, null))
  17. {
  18. var states = stateList.ToList();
  19. return states;
  20. }
  21. else
  22. {
  23. return null;
  24. }
  25. }
  26. [HttpGet]
  27. public JsonResult GetJsonCity(int stateId)
  28. {
  29. var list = new List<CollegeTrackerModels.City>();
  30. try
  31. {
  32. var httpClient = new HttpClient();
  33. httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
  34. HttpResponseMessage response;
  35. response = httpClient.GetAsync("http://localhost:59866/api/" + "cityDetails/GetAllCityDetails?stateId="+stateId+"").Result;
  36. response.EnsureSuccessStatusCode();
  37. List<City> cityList = response.Content.ReadAsAsync<List<City>>().Result;
  38. if (!object.Equals(cityList, null))
  39. {
  40. var cities = cityList.ToList();
  41. foreach (var item in cities)
  42. {
  43. list.Add(new City
  44. {
  45. Value = item.City_ID,
  46. Text = item.City_Name
  47. });
  48. }
  49. }
  50. }
  51. catch (HttpException ex)
  52. {
  53. throw new HttpException(ex.Message);
  54. }
  55. catch (Exception ex)
  56. {
  57. throw new Exception(ex.Message);
  58. }
  59. return Json(new SelectList(list, "Value", "Text"), JsonRequestBehavior.AllowGet);
  60. }

Step 2

Add the following code before the table in the Views/CollegeDetails/CollegeDetails page:

  1. <p>
  2. @Html.ActionLink("Create New", "CreateCollegeDetails", "CollegeDetails")
  3. </p>

Step 3

Go to Views/CollegeDetails and add an empty view named "CreateCollegeDetails" and replace the code with the following code:

  1. @model CollegeTrackerModels.CollegeDetails
  2. @{
  3. ViewBag.Title = "Create CollegeDetails";
  4. }
  5. <h2>Create</h2>
  6. <script type="text/javascript">
  7. function getCities() {
  8. var stateID = $('#DropDownListStates').val();
  9. if (stateID > 0)
  10. {
  11. $.ajax({
  12. url: "@Url.Action("GetJsonCity","CollegeDetails")",
  13. data: { stateId: stateID },
  14. dataType: "json",
  15. type: "GET",
  16. success: function (data) {
  17. var items = "";
  18. items = "<option value=''>--Choose City--</option>";
  19. $.each(data, function (i, item) {
  20. items += "<option value=\"" + item.Value + "\">" + item.Text + "</option>";
  21. });
  22. $('#DropDownListCities').html(items);
  23. }
  24. });
  25. }
  26. }
  27. </script>
  28. @using (Ajax.BeginForm("CreateUpdateCollegeDetails","CollegeDetails",null))
  29. {
  30. @Html.AntiForgeryToken()
  31. <div class="form-horizontal">
  32. <hr />
  33. @Html.ValidationSummary(true)
  34. <div class="form-group">
  35. @Html.LabelFor(model => model.CollegeName, new { @class = "control=label col-md-2" })
  36. <div class="col-md-10">
  37. @Html.EditorFor(model => model.CollegeName)
  38. @Html.ValidationMessageFor(model => model.CollegeName)
  39. </div>
  40. </div>
  41. <div class="form-group">
  42. @Html.LabelFor(model => model.CollegeAddress, new { @class = "control=label col-md-2" })
  43. <div class="col-md-10">
  44. @Html.EditorFor(model => model.CollegeAddress)
  45. @Html.ValidationMessageFor(model => model.CollegeAddress)
  46. </div>
  47. </div>
  48. <div class="form-group">
  49. @Html.LabelFor(model => model.CollegePhone, new { @class = "control=label col-md-2" })
  50. <div class="col-md-10">
  51. @Html.TextBoxFor(model => model.CollegePhone)
  52. @Html.ValidationMessageFor(model => model.CollegePhone)
  53. </div>
  54. </div>
  55. <div class="form-group">
  56. @Html.LabelFor(model => model.CollegeEmailID, new { @class = "control=label col-md-2" })
  57. <div class="col-md-10">
  58. @Html.EditorFor(model => model.CollegeEmailID)
  59. @Html.ValidationMessageFor(model => model.CollegeEmailID)
  60. </div>
  61. </div>
  62. <div class="form-group">
  63. @Html.LabelFor(model => model.ContactPerson, new { @class = "control=label col-md-2" })
  64. <div class="col-md-10">
  65. @Html.EditorFor(model => model.ContactPerson)
  66. @Html.ValidationMessageFor(model => model.ContactPerson)
  67. </div>
  68. </div>
  69. <div class="form-group">
  70. @Html.LabelFor(model => model.StateId, new { @class = "control=label col-md-2" })
  71. <div class="col-md-10">
  72. @Html.DropDownListFor(model => model.StateId, new SelectList(Model.States, "State_ID", "State_Name"), "Choose State", new { onchange = "getCities()", @id = "DropDownListStates" })
  73. @Html.ValidationMessageFor(model => model.StateId)
  74. </div>
  75. </div>
  76. <div class="form-group">
  77. @Html.LabelFor(model => model.CityId, new { @class = "control=label col-md-2" })
  78. <div class="col-md-10">
  79. @Html.DropDownListFor(model => model.CityId, new SelectList(Model.Cities, "City_ID", "State_ID", "City_Name"), "Choose City", new { @id = "DropDownListCities" })
  80. @Html.ValidationMessageFor(model => model.CityId)
  81. </div>
  82. </div>
  83. <div class="form-group">
  84. <div class="col-md-offset-2 col-md-10">
  85. <input type="submit" value="Create" class="btn btn-success" />
  86. </div>
  87. </div>
  88. </div>
  89. }
  90. <div>
  91. @Html.ActionLink("Back to List", "GetCollegeList")
  92. </div>
  93. @section Scripts{
  94. @Scripts.Render("~/bundles/jqueryval");
  95. }

Step 4

Now run the project and click on the Create New Action Link as shown below:

Create New Action Link

Step 5

In the next page you can check that the states are listed in the States dropdownlist.

Cascading Dropdown List

Step 6

Choose the state and the city dropdownlist will update.

City Selection in Cascading Dropdownlist

That's it.

Summary

This article described how to show the cascading dropdownlist based upon the selection of a different state. In the next article we will do the Insert, Delete and Update operation using an API controller using MVC 5. Thanks for reading.