Creating a simple dynamic menu in ASP.NET MVC

Menus are one of the most basic elements on any website, but there’s not a simple dynamic menu out of the box in ASP.NET MVC.  There are several third party solutions you can add as an HTML helper or in a controller, but in several projects I’ve needed a simple and quick way to generate a menu.  Here’s an updated version of something I wrote a while ago in just such an occasion.

We’ll use VS 2010 and the new jQuery Menu widget for the UI (the standard menu CSS won’t work).  You can use any CSS or JavaScript menu UI you want to–I’m using jQuery because it’s free and easy.  You can find the Git repo for this project at https://bitbucket.org/rjdudley/simple-dynamic-menu-in-mvc.

1. Start by creating a new ASP.NET MVC 4 Internet Application.

2. The default template installs jQuery 1.7.1 and jQuery 1.8.2, but the menu widget was released in jQuery 1.9 and jQuery UI 1.10.  The easiest way to update jQuery and jQuery UI is via NuGet.  Install both the latest jQuery and jQuery UI.

One glitch in this sample is the jQuery menu widget–this is a vertical menu.  A horizontal menu will be in the menubar widget, which has not yet been released.  It was supposed to be in 1.9 but didn’t make the cut.  Not a big deal, since this isn’t a post about the UI, but fair warning.

3. Let’s make the jQuery menu work first.  Open Content/Site.css, and find around line 180 where the menu styles are.  Comment out all of the menu styles, it should be about 25 lines of code total.  These styles will conflict with the jQuery menu.

4. To help prevent page flash oafter loading and to make sure all CSS elements are in place before a script is executed, we load CSS files at the top of the page.  Just below the Styles.Render directive, add links for jquery.ui.core.css, then jquery.ui.menu.css.  The code should look like this:

@Styles.Render("~/Content/css")
<link href="../../Content/themes/base/jquery.ui.core.css" rel="stylesheet" type="text/css" />
<link href="../../Content/themes/base/jquery.ui.menu.css" rel="stylesheet" type="text/css" />
@Scripts.Render("~/bundles/modernizr")

5. Next, open up layout.cshtml and scroll down to the bottom of the file. Add a Scripts.Render directive for jQuery UI underneath the one for jQuery, then a small script block to call the jQuery menu function.  The code should look like this:

@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryui")

<script>
$(document).ready(function () {
$("#menu").menu();
});
</script>

@RenderSection("scripts", required: false)

 

(If you want to see how these bundles are defined, open up App_Start/BundleConfig.cs.  Later on you may want to configure all of these scripts and CSS into a bundle)

6.  If we load and run the page now, we should now have a fully functional vertical menu.  Good enough for this demo.

7. We need a model for a MenuItem, so create MenuItem.cs with the following code:

using System;
using System.Collections.Generic;

namespace SimpleMenuSample.Models
{
public class MenuItem
{
public MenuItem()
{
this.ChildMenuItems = new List<MenuItem>();
}

public int MenuItemId { get; set; }
public string MenuItemName { get; set; }
public string MenuItemPath { get; set; }
public Nullable<int> ParentItemId { get; set; }
public virtual ICollection<MenuItem> ChildMenuItems { get; set; }

}
}

 

 

8. Now we need a model for the Menu, so create menu.cs with the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SimpleMenuSample.Models
{
public class Menu
{
public Menu()
{
Items = new List<MenuItem>();
}

public List<MenuItem> Items;
}
}

 

 

9. Now that we have our models defined, it’s time to add a controller method to generate the menu.  Normally you’d do some data access, but we’re going to hard code the menu items here for the sake of simplicity.  Open HomeController.cs and add the following code:

[ChildActionOnly]
public ActionResult Menu()
{
var _menu = new Menu();

// Normally you'd do some data or cache access to build/retrieve the user's menu
// then you're loop through the results and build the menu object
// we're hard coding for the sake of simplicity

var _google = new MenuItem()
{
MenuItemName = "Google",
MenuItemPath = "http://google.com/",
};

_google.ChildMenuItems.Add(new MenuItem()
{
MenuItemName = "Google Images",
MenuItemPath = "http://google.com/images/"
});

var _bing = new MenuItem()
{
MenuItemName = "Bing",
MenuItemPath = "http://bing.com/"
};

_bing.ChildMenuItems.Add(new MenuItem()
{
MenuItemName = "Bing Images",
MenuItemPath = "http://bing.com/images/"
});

_menu.Items.Add(_google);
_menu.Items.Add(_bing);

return PartialView("_Menu", _menu);
}

 

 

10. Now that we have a model and a controller, we need a view to display our menu.  Create a shared view named _Menu.cs with the following code:

@model SimpleMenuSample.Models.Menu
<ul id="menu">
@foreach (var item in Model.Items)
{
<li><a href="@item.MenuItemPath">@item.MenuItemName</a>
@if (item.ChildMenuItems.Any())
{
<ul>
@foreach (var subitem in item.ChildMenuItems)
{
<li><a href="@subitem.MenuItemPath">@subitem.MenuItemName</a></li>
}
</ul>
}
</li>
}
</ul>

 

11. One final change is to call the menu from _Layout.cshtml.  Change the nav element to look like the code below:

<nav>
@Html.Action("Menu","Home")
</nav>

 

And that should be a bingo!  When you run the project, you should see a (rather ugly) vertical menu (seen below).  Hovering over one of the options should cause the child entry to appear.

image

Hope this helps!

ASP.NET MVC Firestarter in Pittsburgh

Coming soon to Pittsburgh:

When it comes to design patterns, the MVC is the granddaddy of them all.  First described in the late 70s, the MVC pattern remains very popular in the world of web applications today. ASP.NET MVC provides a framework that enables you to easily implement the model-view-controller (MVC) pattern for Web applications. This pattern lets you separate applications into loosely coupled, pluggable components for application design, processing logic, and display.

Throughout the day we will be demonstrating the ASP.NET MVC Framework in a cookbook-style approach with recipes on how to solve common challenges when developing MVC web applications. No previous knowledge or experience is necessary. We will walk you through the basics on creating views and controllers and by the end of the day show you how to develop end-to-end MVC applications complete with ajax, authentication, authorization, caching, databinding, logging, persistence, validation, and other common challenges we experience in day-to-day development.

Sample code will leverage and integrate popular frameworks and libraries like ADO.NET Data Services, ASP.NET AJAX, ASP.NET Dynamic Data, Enterprise Library, Entity Framework, and LINQ To SQL to show you how to write less code and be more productive during your development.

Polish it all off with examples showing the extensibility of the MVC Framework using custom controller factories, alternative view engines, and custom action filter attributes just to name a few.

Topics covered will include “How Do I…”

– Create Views Easily? ( HTML and Url Helpers )
– Handle Get and Post Requests? ( simple databinding of action method arguments, ActionResults, etc.. )
– Pass Data Between Views and Controllers? ( ViewData and TempData )
– Bind Views and Forms to complex data types? ( ModelBinders )
– Handle Errors Gracefully? ( ActionFilter Attributes )
– Provide Input Error Validation? ( ValidationMessage, ValidationSummary, ViewData.ModelState )
– Handle Authentication and Authorization? ( ActionFilter Attributes and Membership Provider )
– Persist to a database ( LINQ To SQL, Entity Framework )
– Log Messages to Database, File, EventLog ( ActionFilter Attributes, etc. )
– Leverage AJAX and JSON? ( ASP.NET AJAX and jQuery )

Some of the more complex and non-beginner topics can be discussed if time is allowed and/or maybe discussed afterwards in a social environs…

– Alternate View Engines
– IoC and Custom Controller Factories
– Unit Testing

Bring your USB Flash Drive to grab the sample code and begin developing ASP.NET MVC Web Applications today!

Register online at http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032392363&culture=en-US.