implementing a cascading dropdown list with MVC and Jquery

By definition (my own) a cascading dropdown list(s) is a set of dropdown list(s) dependent on their parent dropdown list. In this blog post we’ll see how this can be achieved in ASP.NET’s MVC pattern, with the help of some client-side scripting too. For simplicity I will be using the standard template that Visual Studio creates for you when you create a new project. Also, I uploaded the source code to this GitHub location.

All right so let’s say that we’re going to have three dropdown lists, and through these we will be able to drill down from continent, to countries, to cities. All the data in this project is hard coded but it can easily be retrieved from a database or some other source. So first thing we’ll do is update the Index method in the HomeController to make it look like the following;


public ActionResult Index()
{
continents = new List();
continents.Add(new SelectListItem { Text = "Select continent", Value = "0" });
continents.Add(new SelectListItem { Text = "Europe", Value = "1" });
continents.Add(new SelectListItem { Text = "North America", Value = "2" });
continents.Add(new SelectListItem { Text = "South America", Value = "3" });
ViewData["continents"] = continents;
countries = new List();
countries.Add(new SelectListItem { Text = "Select country", Value = "0" });
ViewData["countries"] = countries;
cities = new List();
cities.Add(new SelectListItem { Text = "Select city", Value = "0" });
ViewData["cities"] = cities;
return View();
}

So we created three lists of type SelectListItem and filling them with some data, and then passing them to our view using the ViewData. These lists can also be bound to a model and then pass the model to the view. I chose the ViewData option for simplicity. Within the view we need to create three dropdown lists and make a reference to the ViewData.


<div class="row">
<div class="col-md-4">
@Html.DropDownList("continents", ViewData["continents"] as List)
</div>
<div class="col-md-4">
@Html.DropDownList("countries", ViewData["countries"] as List)
</div>
<div class="col-md-4">
@Html.DropDownList("cities", ViewData["cities"] as List)
</div>
</div>

Now we got three dropdown lists with some data in them. For the next part we need to add some client-side scripting so we can load more data dynamically. Using Jquery we will make an AJAX call and get data according to what the user selected.


$("#continents").change(function () {
$("#countries").empty();
$.ajax({
type: 'POST',
url: '/Home/GetCountries',
dataType: 'json',
data: { selectedValue: $("#continents").val() },
success: function (areas) {
$.each(areas, function (i, area) {
$("#countries").append('' + area.Text + '');
});
},
error: function (ex) {
alert('Failed to retrieve countries.' + ex);
}
});
return false;
});
$("#countries").change(function () {
$("#cities").empty();
$.ajax({
type: 'POST',
url: '/Home/GetCities',
dataType: 'json',
data: { selectedValue: $("#countries").val() },
success: function (cases) {
$.each(cases, function (i, ucase) {
$("#cities").append('' + ucase.Text + '');
});
},
error: function (ex) {
alert('Failed to retrieve cities.' + ex);
}
});
return false;
});

Back to the HomeController we are going to create two entry points and do our logic in there.


public JsonResult GetCountries(string selectedValue)
{
countries = new List();
countries.Add(new SelectListItem { Text = "Select country", Value = "0" });
switch (selectedValue)
{
case "1":
countries.Add(new SelectListItem { Text = "United Kingdom", Value = "1" });
countries.Add(new SelectListItem { Text = "Italy", Value = "2" });
countries.Add(new SelectListItem { Text = "Greece", Value = "3" });
break;
case "2":
// more countries
break;
case "3":
// more countries
break;
}
return Json(new SelectList(countries, "Value", "Text"));
}
public JsonResult GetCities(string selectedValue)
{
cities = new List();
cities.Add(new SelectListItem { Text = "Select city", Value = "0" });
switch (selectedValue)
{
case "1":
cities.Add(new SelectListItem { Text = "Glasgow", Value = "1" });
cities.Add(new SelectListItem { Text = "London", Value = "2" });
cities.Add(new SelectListItem { Text = "Edinburgh", Value = "3" });
break;
case "2":
// more cities
break;
case "3":
// more cities
break;
case "4":
// more cities
break;
case "5":
// more cities
break;
// more cases
}
return Json(new SelectList(cities, "Value", "Text"));
}

And that should be it. Feel free to share your thoughts if you have any suggestions. Until the next post.

Bjorn

css tricks for text selection

So recently I had to disable text selection for some web pages and after a quick Google search I realized that this could be achieved through CSS – great stuff!! 😀

First thing I did was create a new HTML page, wrote some dummy text and applied some CSS to test it out. Loaded the HTML in the browser and tried to select the dummy text. The text could not be select – awesome! The CSS I tried out was the following;


-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;

view raw

csstricks.css

hosted with ❤ by GitHub

The different styling is added to ensure that the styling is rendered properly on different web browsers. I then dug a bit deeper and tried out different CSS implementations related to text selection. I create a working JSFiddle with the said CSS and it can be accessed via this link. The JSFiddle has three different styles

  • No text selection
  • One click, all text selection
  • Different colors shown when selecting text

Until next time,
Bjorn

loading a video at client-side level

Imagine a scenario where you want to load media, or any other form of content, from the user’s computer rather than retrieving the content from the web server and consuming bandwidth every time the pages is loaded or refreshed – and this can be quite pricey if the content you’re loading is a video. That being said, having a web application that can access the user’s file directory poses a serious security threat as this makes the user’s computer vulnerable to threats with not so friendly intentions. So, whilst keeping this security issue in mind, let’s create a scenario where we retrieve the HTML, and other web content such as CSS and Javascript, from the web server but load the interactive content from the file directory.

Let’s start by creating a simple HTML file and add a HTML5 video tag linked to a video.


<html>
<head></head>
<body>
<h1>Hello World</h1>
<video width="640" height="360" controls="controls">
<source src="./PlayStationStartup.mp4" type="video/mp4">
</video>
</body>
</html>

Run this on your browser and it should look something like this.

1

At this point let’s try and mimic the behavior of a web server by loading this HTML file on the Internet Information Services(IIS). I created a simple web site with a specific port(3001) and set it’s directory to where the HelloWorld.html is. Typing http://127.0.0.1:3001/helloworld.html in the browser’s address bar loaded the page as intended and the video still running just like it was before. So far so good. At this point the video is still in the same directory as the HTML file. I re-modeled the file system and created the following structure:

ROOT
– Server One
– – HelloWorld.html
– Server Two
– – PlaystationStartup.mp4

Server One is the web server where the HTML file is hosted and Server Two is the location of the video on the user’s computer. When I tried to edit the source of the video and changed it to the direct path, the video did not load and the following error showed up in the browser’s console.

2

One way to work around this is to host the video on the IIS at client-side and then make a reference to it, specifically by its port and file name, from the HTML file. I created another site on the IIS and mapped it on the new Server Two folder. I then edited the HTML file and the value of the source attribute was changed as below.


<html>
<head></head>
<body>
<h1>Hello World</h1>
<video width="640" height="360" controls="controls">
<source src="http://127.0.0.1:3002/PlayStationStartup.mp4&quot; type="video/mp4">
</video>
</body>
</html>

The web page was refreshed and the video loaded as intended. Even though the above is one way to load content from the user’s computer I still think that ideally content should be retrieved from the web server. However, in case of a closed environment and with certain strict conditions, it’s good to know that there are alternatives.

Adios,
Bjorn