C#
 ASP.NET
 MVC
 Visual Studio 2015
One of the most common controls on a web form are Drop Down Lists, where a value is selected from a pre-defined ists of values. These don't normally change very often and so it soon becomes obvious it is a waste of resources to constantly retrieve them from where they are persisted, usually a database, and loaded over and over again.
If they are shared by all users a simple solution to this is to retrieve them once and store them in Application state. The Drop Down controls can then be reloaded from memory each time, and not have to access a database.
This builds on an earlier article on how to use Application state How To Cache Data in Application State for ASP.NET MVC.
Here is a simple process to populate Drop Down Lists from cached data stored in Application state for ASP.Net MVC web applications.
1. Create a new Visual Studio 2015 project
2. Select 'ASP.Net Web Application'
3. Change the name to 'MVCDropDownListDemo' and press OK
4. Select 'MVC' and Change Authentication to 'No Authentication' and press OK to create the project
5. In the root directory create a new class called 'Location', this is the collection of objects that will cached. Add the following properties to the Location class:
namespace MVCCachedDropDownListDemo
{
public class Location
{
public int Id;
public string Name;
}
}
6. In the Models directory create a new class called 'Home_Index_Model'. I always create a model per page to hold whatever data that page will need, or return, and name it to reflect its location. Add the following properties to the Location class:
using System.Collections.Generic;
using System.Web.Mvc;
namespace MVCCachedDropDownListDemo.Models
{
public class Home_Index_Model
{
//selected value
public int LocationId { get; set; }
//collection of objects
public IEnumerable Locations { get; set; }
}
}
LocationId - will be populated with the value of the item selected in the DropDownList and returned to the controller in the Post.
Locations - is populated with a collection of SelectListItems representing the collection of Location objects.
7. Create a new folder in the root directory called 'Common'
8. In Common, create a new class called ApplicationCache. Note it is static as it will be shared by all users. Replace the code with the following code:
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ApplicationCacheDemo.Common
{
public static class ApplicationCache
{
public static HttpContext httpContext { get; set; }
//get a fresh list of Location objects from the Database
public static void CacheLocations()
{
var location = new Location();
IList locations = new List();
foreach (var item in GetLocationsFromDB().OrderBy(x => x.Name).ToList())
{
locations.Add(item);
}
httpContext.Application["Locations"] = locations;
}
//return a list of cached Location objects
public static IList Locations
{
get
{
object obj = httpContext.Application["Locations"];
if (obj == null)
{
CacheLocations();
obj = httpContext.Application["Locations"];
}
return (IList)obj;
}
}
//Clear Locations from the Application cache
public static void LocationsClear()
{
httpContext.Application["Locations"] = null;
}
//replace with code to retrieve list from Database
private static IList GetLocations()
{
var locations = new List() {
new Location()
{
Id = 1,
Name = "Wolverhampton"
},
new Location()
{
Id = 2,
Name = "Brisbane"
},
new Location()
{
Id = 3,
Name = "Reading"
},
new Location()
{
Id = 4,
Name = "Dartmoor"
}
};
return locations;
}
}
}
This has 3 main methods:
Locations - retrieves the contents of "Locations" (collection of Location objects) from Application state and checks if it populated. If it is, it returns the collection. If not, it calls CacheLocations() to load them.
CacheLocations() - retrieves the collection of Location objects from wherever they are persisted. This would normally be from a database, but for simplicity in this example it calls local procedure GetLocations() which just returns a hard coded list.
LocationsClear() - clears Application state for Locations, so the next request for the collection will cause the data to be freshly loaded. If the data should ever be changed, we would call this to trigger its reloading a fresh set.
9. In the HomeController replace the code for Index() with the following code:
[HttpGet]
public ActionResult Index()
{
var model = new Home_Index_Model();
ApplicationCache.httpContext = System.Web.HttpContext.Current;
model.Locations = ApplicationCache.Locations.Select(x => new SelectListItem { Value = x.Id.ToString(), Text = x.Name }).ToList();
return View(model);
}
[HttpPost]
public ActionResult Index(Home_Index_Model model)
{
var selectedLocationId = model.LocationId;
model.Locations = ApplicationCache.Locations.Select(x => new SelectListItem { Value = x.Id.ToString(), Text = x.Name }).ToList();
return View(model);
}
The [HttpGet] retrieves the collection of Locations that are cached in Application state and builds a collection of SelectListItem objects from them.
The [HttpPost] returns the selected value from the DropDownList in LocationId.
10. In Views -> Home replace markup for Index.cshtml
@model MVCCachedDropDownListDemo.Models.Home_Index_Model
@{
ViewBag.Title = "Home Page";
}
@using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
@Html.Label("Locations:")
@Html.DropDownList("LocationId", (IEnumerable)Model.Locations, null, new { @tabindex = 1 })
}
The DropDownList is created by @Html.DropDownList(). The "LocationId" specifies where the selected value is to be stored. This will be returned to the controller in the Post.
11. The view of the selectable DropDownList