There are many ways to populate a dropdown control using MVC. The data used to populate the control can come from multiple sources, it can be a database, an enum, a list or any other data structure we have access. Usually the controller puts together the required information and passes it to the view.
Today we will see how we can transfer this responsibility to an action filter, helping us to clear our controller code a bit.
Let’s begin by creating the classes we will be playing with.
First let’s create our very simple model:
public class Blog
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
}
Now let’s create the viewmodel class we will pass to our view from the controller:
public class BlogsViewModel : IBlogList
{
public List<Blog> Blogs { get; set; }
}
Notice that our view model implements the IBlogList, which is a very simple interface:
public interface IBlogList
{
List<Blog> Blogs { get; set; }
}
Now the controller action:
public ActionResult Blogs()
{
var model = new BlogsViewModel();
return View(model);
}
Our view will take a BlogsViewModel as model and will render a dropdown list using the options contained in the Blogs property of the model.
@model DataLoader.Models.BlogsViewModel
…
@Html.DropDownList(“blog”, new SelectList(Model.Blogs, “Id”, “Title”), “Select blog”,new { @class = “form-control” })
…
Let’s implement now the action filter where the magic is happening:
public class BlogsDropdownPopulatorAttribute : ActionFilterAttribute
{
private List<Blog> GetBlogs()
{
var blogList = new List<Blog>();
blogList.Add(new Blog() { Id = 1, Title = “First Blog”, Content = “First blog’s content” });
blogList.Add(new Blog() { Id = 2, Title = “Second Blog”, Content = “Second blog’s content” });
return blogList;
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if(filterContext.Result is ViewResult)
{
var viewResult = filterContext.Result as ViewResult;
if(viewResult.Model is IBlogList)
{
(viewResult.Model as IBlogList).Blogs = GetBlogs();
}
}
}
}
Notice that our filter is extending the ActionFilterAttribute class. Now we can overwrite the OnActionExcecuted where we can populate the Blogs property of the model only if the model implements the IBlogList interface and the result is a ViewResult. For sake of simplicity, we are returning a static list of blogs but this could be coming from our database or other source.
If we run our code now, we will getSystem.ArgumentNullException because the Blogs property is not populated yet but if we decorate the controller action with our brand new action filter and run the project again, TA-DA, the dropdown list is correctly populated.
[BlogsDropdownPopulator]
public ActionResult Blogs()
{
var model = new BlogsViewModel();
return View(model);
}
Notice that we can now decorate not only the action method with our filter, we can also decorate our controller class too and all the view models for each action methods that implements the IBlogList interface will have the Blogs property automagically populated.
Here at Palm Beach Software, we take great pride in our ability to identify and discuss requirements, examine all avenues, and develop a thorough and well thought out plan. All of this helps to develop our projects foundation so that we can provide you with the highest quality software package.