Azure, MVC, MVC 3, MVC4, Technical

Redirecting legacy pages in

Picture this situation.

An old (legacy) application has landed on your project pile. It is largely built in php, and you intend on re-writing it in MVC.

You will therefore need to somehow inform any parties that may be trying to access the old urls ending in .php, that the resource they are looking for has moved permanently. You may also wish to do this for SEO reasons.

This is something that cannot be achieved easily through routing; by default, IIS will not pass requests for resources ending in .php to your application. Your routing will therefore never be put to use for resources ending with .php.

The nicest solution I found to this issue is to setup a list of redirects within the system.Webserver section of your web.config file. The following listing below will send a HTTP Response status of 301 (Moved Permanently) for any requests for index.php and for prices.php:

 <httpRedirect enabled ="true" httpResponseStatus="Permanent" exactDestination="true">
 <add wildcard="/prices.php" destination="/prices"/>
 <add wildcard="/index.php" destination="/"/>

Index.php will now redirect to /, and prices.php will now redirect to /prices.

This code is currently running in the wild on Azure.

If you are unsure if you need a Permanent redirect or not, have a read of this article from Google.

MVC 3, MVC4, Razor, Technical

Using MVC4 bundling and minification in an MVC3 project

When you push any site to production, you should at least do some basic front end optimisation. Running through a number of optimisation steps will ultimately make your website load quicker and feel more responsive to the end user.

If this is the first you have heard about front end optimisation, I must recommend that you read “High Performance Websites” by Steve Souders.

One of the best ways to make your site load quicker is to make it smaller. Reduce the amount of data that needs to go from your server to the client machine. And one of the best ways to make massive gains in doing this is to Bundle and Minify the CSS and Javascript that your application uses.

MVC4 has made this incredibly easy with built in Bundling and Minification. However, you do not need to upgrade your entire MVC project to take advantage of this fantastic new set of features.

Firstly, open up the project that you want to optimise. I’ll be demonstrating this with a new empty MVC3 web application. Currently, the head of my _Layout.cshtml file looks like this:

 <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
 <script src="@Url.Content("~/Scripts/jquery-1.7.1.js")" type="text/javascript"></script>
 <script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
 <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
 <script src="@Url.Content("~/Scripts/modernizr-2.5.3.js")" type="text/javascript"></script>

So lets run the page and just see what’s going on under the hood:


So at the moment, my page is a massive 355.89 Kilobytes – and all it does is display some text – “Index”. That’s way too big – and we can see that the biggest and slowest loading areas of the site are the Javascript libraries that are being pulled onto every page of the site. (It’s worth noting at this point that you could used the already minified versions of the files. For the sake of this demo, I’ll be using the full fat versions).

So let’s get bundling and minifying.

Open the package manager console, and enter the following command to drag down the Microsoft ASP.NET Web Optimization Framework:

  •  Install-Package Microsoft.AspNet.Web.Optimization -Pre

Once added to your project, you can the begin configuring your bunding and minification. Open your Global.asax.cs file and add a reference to System.Web.Optimization

using System.Web.Optimization;

Then, go ahead and create a new static method, RegisterBundes:

public static void RegisterBundles(BundleCollection bundles)


Now, lets create some Bundles. I’m going to put all of my Javascript into one minified bundle, and my CSS into another minified bundle:

public static void RegisterBundles(BundleCollection bundles)
 var styles = new StyleBundle("~/Content/bundledcss").Include("~/Content/site.css");

 var js = new ScriptBundle("~/Scripts/bundledjs").Include("~/Scripts/jquery-1.7.1.js",

 BundleTable.EnableOptimizations = true;

There are three types of bundle that you can create:

  • Bundle – a non-minified bundle of a collection of files
  • StyleBundle – a minified bundle of a collection of css files
  • ScriptBundle – a minified bundle of a collection of Javascript files

Now, lets wire up a call to our new RegisterBundles method. In Global.asax.cs, locate your Application_Start method. Add the following line:


Now, when your application starts up, the bundles will be created. Now, all we need to do is to tell the views that they now need to load a bundled file and not the raw, unbundled and unminified css and js files.

In your _layout.cshtml file, or whichever file you have your stylesheets and javascript files referenced, swap out your raw file references. Firstly, add a reference at the top of your view to System.Web.Optimisation:

@using System.Web.Optimization

Now, lets swap the old references to our full fat files out:

 <link rel="stylesheet" type="text/css; href="@BundleTable.Bundles.ResolveBundleUrl("~/Content/bundledcss")" />
 <script src="@BundleTable.Bundles.ResolveBundleUrl("~/Scripts/bundledjs")">"</script>

And that’s us. Let’s test it out. Remember to build first:


And we’ve made a massive improvement. We have:

  • Reduced the number of requests (from 6 to 3, as we’ve bundled multiple files into one
  • Reduced the file sizes

This won’t take long to bring into an existing site and is definitely worth the benefits.

Edit: Of course, you should also move your Javascript to the foot of the html document for even more speed improvements.

MVC 3, Technical, Unit Testing

Mocking HttpContext (And setting it’s session values)

Thanks to this Stack Overflow answer that pushed me in the right direction, I was able to mock HttpContext and set values that it encompasses.

Firstly, you will need a helper somewhere in your test project that will return you a mock HttpContext:

public static class MockHelpers
  public static HttpContext FakeHttpContext()
    var httpRequest = new HttpRequest("", "http://localhost/", "");
    var stringWriter = new StringWriter();
    var httpResponce = new HttpResponse(stringWriter);
    var httpContext = new HttpContext(httpRequest, httpResponce);

    var sessionContainer = new HttpSessionStateContainer("id", new SessionStateItemCollection(), new HttpStaticObjectsCollection(), 10, true, HttpCookieMode.AutoDetect, SessionStateMode.InProc, false);

    SessionStateUtility.AddHttpSessionStateToContext(httpContext, sessionContainer);

    return httpContext;

You will then need to Add and Reference System.Web in your test project. Once done, you will be able to set your HttpContext and set HttpContext specific values, such as session variables. In the example below, I am setting up the HttpContext in the SetUp method of a unit test:

public void SetUp()
	HttpContext.Current = MockHelpers.FakeHttpContext();
	HttpContext.Current.Session["SomeSessionVariable"] = 123;

Another more heavy solution to the above would be to use a factory to get at and create your session. I opted for the solution above as it meant not changing my application code to fit in with my unit tests.

MVC 3, MVC4, Technical

Dependency Injection with ninject.mvc3 nuget

Quick post, just because this is mega easy.

Traditionally, adding dependency injection with any standard injection package to an MVC solution would normally mean that you would have to write a Controller Factory and wire it up in your Application_Start() method.

If you want to add dependency injection into an MVC solution, just add one of the pre-baked nuget packages that does the MVC wire up for you:

It’s just much easier – these packages contain code that has done the legwork of wiring up a custom controller factory for you.

Looking specifically at the Ninject.MVC3 package, simply add the NuGet reference. This will add a “NinjectWebCommon.cs” file into your “App_Start” folder:

You can then edit the RegisterServices(IKernel kernel) method to configure your bindings:

        private static void RegisterServices(IKernel kernel)
Entity Framework, MVC 3, Technical

Entity Framework – Plural and Singular Table names

By default, the Entity Framework will assume that all of the names of your tables in your database are either pluralised, or in the case of code first, you would like them to be pluralised when created.

E.g. you have a table called “Product” and not “Products”, or you want your table to be called “Product” and not “Products”

This is the problem that I had. My MVC application consisted of one web page that just dumped out the contents of the “Product” table onto the page. When I browsed to the page, I got an “Invalid object name ‘dbo.Products’.” yellow screen of death runtime error.

The Solutions

1. Rename the table to “Products”. I didn’t want to do this as I’m from the school of singular table names. I was also curious about situations where the tables couldn’t be renamed.

2. Make use of Entity Framework’s fantastic Conventions, that allow you to specify how you have or want your database to be setup.

To tell Entity Framework not to pluralise database table names, simply add the following code into your DbContext class:

public class EfDbContext : DbContext
  public DbSet&lt;Product&gt; Products { get; set; }
  protected override void OnModelCreating(DbModelBuilder modelBuilder)

This code will remove the Pluralising convention that is by default attached to all model builders. You will then be able to access database tables with Singular names.


Table Naming Dilemma: Singular vs. Plural Names (StackOverflow)

PluralizingTableNameConvention Class (MSDN)

MVC 3, Razor, Sitemaps, Uncategorized

MVC Sitemap Provider tutorial 2 – Breadcrumbs

Once you’ve got your sitemap correctly configured and setup, you will be looking to use some of the features of a Sitemap – for example, breadcrumbs. In this post we will start with an empty MVC3 project, and add the sitemap provider, a few controller actions and corresponding views, and we will have the provider produce some breadcrumbs for us.


Lets start from an Empty MVC3 project. Fire up Visual Studio. Create a new Asp.Net MVC3 Web application. I’m going to call mine SitemapDemo:

Create new MVC3 project

For the sake of this demonstration, I have selected an empty template and have chosen Razor as my view engine.

Now before we go any further, lets go ahead and install the NuGet package.  Select View > Other Windows and then select “Package Manager Console”:

Package Manager Console Location VS2010

This will then dock the Package Manager Console somewhere into your view. In order to add the MVC sitemap provider to the current project, we need to enter the following command into the Package Manager Console, and hit enter:

PM> Install-Package MvcSiteMapProvider

This command will then download the necessary files (dlls, cshtml files) and add them into your MVC project. This could take a few minutes depending on your connection. If this has been successful, your Package Manager Console should give you an output similar to the following:

PM> Install-Package MvcSiteMapProvider
Successfully installed 'MvcSiteMapProvider'.
Successfully added 'MvcSiteMapProvider' to SitemapDemo.


Now lets take a look at what exactly the NuGet package manager has added to our project:

  • SitemapDemo > References > MvcSiteMapProvider – This is the reference to the MvcSiteMapProvider dll
  • SitemapDemo > Mvc.sitemap – This file will be used to describe our MVC3 website in XML nodes
  • SitemapDemo > Views > Shared > DisplayTemplates > MenuHelperModel.cshtml
  • SitemapDemo > Views > Shared > DisplayTemplates > SiteMapHelperModel.cshtml
  • SitemapDemo > Views > Shared > DisplayTemplates > SiteMapNodeModel.cshtml
  • SitemapDemo > Views > Shared > DisplayTemplates > SiteMapNodeModelList.cshtml
  • SitemapDemo > Views > Shared > DisplayTemplates > SiteMapPathHelperModel.cshtml
  • SitemapDemo > Views > Shared > DisplayTemplates > SiteMapTitleHelperModel.cshtml

As we’re using Razor as our view engine, we can go ahead and delete the asax files that have been added to the SitemapDemo > Views > Shared > DisplayTemplates folder. Here’s how your solution should now look:

Sitemapdemo Solution Explorer

Now that’s the install over. Let’s add a half decent set of controller actions and views to the site before we go on to playing with the SiteMapProvider. The point of this is to capture the kind of structure that you would find in a typical website.


The MVC Sitemap provider will fail silently in some fashion if we try to force it to work with controller actions that either don’t exist or that point to non existent views. This is why we are doing this stage first.

All sites have a homepage, so lets add this first. Right click on your Controllers folder, and add a controller called “HomeController”. Lets leave the scaffolding options blank:

HomeController-Add Blank

Once your controller is created and open, right click inside the Index action and select “Add View…”

Home Index Add View

In the Add View dialogue that pops up, just go a head hit add. Nothing will need changing.  Now lets change the text inside the created page’s h2 tag on the page – something like “Index – this is the home page” will do.

And now lets add another controller in the same way that we added the HomeController. Let’s call it NewsController. Update the newly created news controller to contain an additional action result called “Sports”:

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

namespace SitemapDemo.Controllers
    public class NewsController : Controller
        // GET: /News/

        public ActionResult Index()
            return View();

        // GET: /News/Sports/
        public ActionResult Sports()
            return View();


Now, lets add a view for each of our newly created NewsController actions. Lets do this in the same way that we added the view for the home page – by right clicking within the body of each controller action. Again, we can simply leave all of the defaults in the “Add View” dialogue and just hit “Add” for both views.

Now edit the h2 tag on the News Index cshtml file to read “News Index”. Lets also edit the h2 tag on the News Sports cshtml file to read “Sports News”.

Let’s now add one more Controller for illustration – AboutController. Once created, you can leave the controller unchanged, and can add a view for the Index controller action. This time, lets change the h2 to tags to read “About Page”.

As we have now added 4 pages to our website, it’s now worth just testing them out before we start integrating the Site Map Provider. Hit the debug button – below are screen shots and their corresponding URLs:


SitemapDemo Index


SitemapDemo News Index


SitemapDemo News Sports


SitemapDemo About Index

Ok, so we’ve now got a small site with a little bit of a structure. Lets represent that structure in an easy diagram:

SitemapDemo Sitemap Diagram

Visualising our layout like this will really help us describe our site’s structure in our Mvc.sitemap file correctly. Our Index page is our wrapper for the entire site as it is the page that sits in the root, and is the first port of call into the site.

Now lets get into configuring our Sitemap. Lets start by editing our Mvc.sitemap file, which is in the root of our project. This file contains all of the xml nodes needed to represent your controller and action combinations.

MVC Sitemap xml file vs

Edit your Mvc.Sitemap file so that it is the same as the listing below:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;mvcSiteMap xmlns=&quot;; enableLocalization=&quot;true&quot;&gt;
  &lt;mvcSiteMapNode title=&quot;Home&quot; controller=&quot;Home&quot; action=&quot;Index&quot;&gt;
    &lt;mvcSiteMapNode title=&quot;News&quot; controller=&quot;News&quot; action=&quot;Index&quot;&gt;
      &lt;mvcSiteMapNode title=&quot;Sports News&quot; controller=&quot;News&quot; action=&quot;Sports&quot;/&gt;
    &lt;mvcSiteMapNode title=&quot;About&quot; controller=&quot;About&quot; action=&quot;Index&quot;/&gt;

We have now represented our website structure / workflow in the MVC.Sitemap file. A classic “gotcha” here is forgetting that your entire site is wrapped in a node that represents your homepage. Your sitemap file must contain this node – after all, your website’s homepage is the page that the client sees as the root of everything. So even though the Index action is actually at yourwebsite/Index, the client will typically see it just as yourwebsite/. The rest of the structure should make sense when compared to the website navigation diagram, earlier in this post.

Adding Navigation

Now that we’ve got some controllers and actions setup, and our site structure described properly in our Mvc.Sitemap file, lets add some navigation to all pages.

Open up your _Layout.cshtml partial, located in the Views/Shared folder. Update the listing so that the code between the body tags looks like this:

    @Html.MvcSiteMap().Menu(false, true, true)

We are now calling the MvcSiteMap library and telling it to output the website’s navigation on every page. The parameters specified mean that:

  • We don’t want it to start from the current node (changing this to true will break it!)
  • We want the starting node to appear in child level
  • We want to show the starting node. Setting this to false will hide the parental “Home” node
And now if we run our application, we should see the navigation laid out on every page, complete with links:
Index with navigation

News with navigation

Editing the navigation appearance

So now we’ve managed to output a simple navigation onto all pages of our website. If you want to change any styling, or how the navigation is displayed, simply alter the code in Views/Shared/DisplayTemplates/MenuHelperModel.cshtml. Lets make a simple change and add an inline style to change our bullet points from circles to squares:

    @foreach (var node in Model.Nodes) {
        &lt;li style=&quot;list-style-type:square;&quot;&gt;@Html.DisplayFor(m =&gt; node)
            @if (node.Children.Any()) {
                @Html.DisplayFor(m =&gt; node.Children)

You can now hit refresh in your browser without needing to re-compile. Your News index page should now look like this:

News Index Square Bullets


We can add breadcrumbs in a similarly easy fashion. Let’s open up our _Layout.cshtml partial and edit the listing:

    @Html.MvcSiteMap().Menu(false, true, true)
    &lt;p&gt;Start of Breadcrumbs:&lt;/p&gt;

Now all pages on our site will have a handy set of breadcrumb links:

News Breadcrumbs MvcSitemap

Sportsnews breadcrumbs MVCSitemap

Similarly, if we want to customise the presentation of our breadcrumbs, we need to change the Views/Shared/DisplayTemplates/SiteMapPathHelperModel.cshtml file.

Dynamic URLs / Parametered URLs

Every real site will need to employ a dynamic / Parametered URL at some point. Incorporating a dynamic URL into the MVC Sitemap is straightforward when you know how. Lets start by adding a new action to the NewsController:

        //GET: News/Article/x
        public ActionResult Article(int id)
   = id;
            return View();

Now lets add a view – right click anywhere within the new action and select “Add View…”. Again, just hit Add – we don’t need to change any of the options. Now update the newly created Article.cshtml file with the following:

    ViewBag.Title = &quot;Article&quot;;

&lt;h2&gt;Viewing Article;/h2&gt;

Now lets browse to localhost:xxxx/News/Article/1234:

News Article 1234 mvcsitemap

Note that this new page does not appear anywhere in our sitemap, and that the breadcrumbs are totally empty.

In order to add the page into our navigation, we must first decide where it needs to go. I’d like this page to sit underneath the News section. So lets edit our Mvc.Sitemap file and add a Key attribute to the “News” node. This is simply to give it a unique identifier:

&lt;mvcSiteMapNode title=&quot;News&quot; controller=&quot;News&quot; action=&quot;Index&quot; key=&quot;News&quot;&gt;

Now we need to decorate our controller action with some attributes that tell it where to insert the action in the site’s structure. Update your Article action in your News controller:

        //GET: News/Article/x
        [MvcSiteMapNode(Title = &quot;Article&quot;, ParentKey = &quot;News&quot;)]
        public ActionResult Article(int id)
   = id;
            return View();

Now lets compile and browse to localhost:xxxx/News/Article/1234:

Article Dynamic MVCSitemap

And we now have Breadcrumbs and navigation for our new page, despite it having a dynamic URL!

Download the Solution

You can download the complete solution here

Recommended Reading:

Pro ASP.NET MVC 3 Framework

MVC 3, Technical

Using MVC remote validation in the real world – AdditionalFields

Implementing remove validation in MVC 3 is very trivial. Typical examples found on the web after a quick search will usually demonstrate the remove validation required when creating a new user. The typical “Is my user name available” check.

However, on putting together a real world MVC 3 application that made full use of models that could be re-used and partials, I hit a pretty obvious issue. In this application, we were using the same model for creating new users and updating existing users. Why wouldn’t we? The model represents the same entity, and will need the same validation. This was a perfect fit and was ideal until we decided to put some remote validation in against the email address field.

Our email address property in our model, after initially adding remote validation, looked something like this:

        [DisplayName(&quot;Email Address&quot;)]
        [Remote(&quot;IsUserNameAvailable&quot;, &quot;UserManagement&quot;)]
        public string ContactEmailPrimary { get; set; }

This worked fantastically on the create user page. When the user entered an email address that was already registered, the client made an Ajax request to our following controller action, that checked if the email address was not already in the database:

        public virtual JsonResult IsUserNameAvailable(string contactEmailPrimary)
                int results = 0;
                var searchResults = _userServiceGateway.SearchUserLogin(contactEmailPrimary);

                if (searchResults.Count &gt; 0)
                    return Json(&quot;This Email Address has already been registered&quot;, JsonRequestBehavior.AllowGet);

                return Json(result, JsonRequestBehavior.AllowGet);

Which if it was registered, would return false.

“Great” we thought. Feature complete – and it went off to the testers. Only for another bug to have come up. We now couldn’t update the user information of an existing user. This was because the remote validation was firing and checking that the email address of the existing users hadn’t already been registered – which, it obviously had. This resulted in our page failing client side validation, and the client being unable to save any changes to the entity.

So we needed a solution. We first explored the possibility of disabling the Remote Validation somehow for this one page. This proved fruitless. We then looked at possibly splitting the models used, and having one model for the User Create, and one model for the User Update. We resisted this idea for obvious reasons.

We then looked at the possibility of passing additional parameters to the Remote Validation action. Sure enough, we discovered the AdditionalFields attribute of the Remote validation object.

The AdditionalFields attribute allows you to specify the name of another form element that will appear within the same form. ASP.NET MVC3 remote validation will then pass the value of this additional attribute to your controller action that is performing the validation. So to fix our issue, we just altered the code to pass the AdditionalField of “UserAccountId”, which we knew would be greater than zero if the user entity was being edited and not created.

Here’s how our finished working code looked, making use of the AdditionalFields attribute:


        [DisplayName(&quot;Email Address&quot;)]
        [Remote(&quot;IsUserNameAvailable&quot;, &quot;UserManagement&quot;, AdditionalFields = &quot;UserAccountId&quot;)]
        public string ContactEmailPrimary { get; set; }
        public int UserAccountId { get; set; }


&lt;div class=&quot;columns&quot;&gt;
 @Html.LabelFor(model =&gt; model.ContactEmailPrimary)
 &lt;span class=&quot;relative&quot;&gt;
 @Html.TextBoxFor(model =&gt; model.ContactEmailPrimary)
 @Html.HiddenFor(model =&gt; model.UserAccountId)


And finally our controller, which now gets an AdditionalField of “UserAccountId”:

        public virtual JsonResult IsUserNameAvailable(string contactEmailPrimary, int userAccountId)
            if (userAccountId == 0)
                int results = 0;
                var searchResults = _userServiceGateway.SearchUserLogin(contactEmailPrimary);
                bool result = true;

                //We need to check for an exact match here as the search only does a &quot;like&quot;
                foreach (var userAccountDto in searchResults)
                    if (userAccountDto.UserLogin == contactEmailPrimary)
                        result = false;
                if (!result)
                    return Json(&quot;This Email Address has already been registered&quot;, JsonRequestBehavior.AllowGet);

                return Json(result, JsonRequestBehavior.AllowGet);
            return Json(true, JsonRequestBehavior.AllowGet);

We were now back to create and update functionality working securely.

Recommended Reading:

Pro ASP.NET MVC 3 Framework

MVC 3, Razor, Sitemaps, Uncategorized

MVC Sitemap Provider tutorial and examples

The MVC sitemap provider is a solution aiming to provide your website with a fully functioning set of sitemap tools, such as breadcrumbs and node navigation.

When delving into using this solution, I made the huge mistake of first not reading up about sitemaps in general. If you do not have any previous experience in using sitemaps on an website, I would strongly recommend reading this MSDN article on sitemaps. Many of the principles used in the MVC framework are the same and reading this article will give you some fundamental basic principles.

Once you get the MVC sitemap provider downloaded and registered, you should see that a sitemap file (Mvc.sitemap) has been created in your MVC solution’s root:

Site Map In Solution

Next, you need to go about editing your MVC.sitemap file so that it actually reflects the pages on your web site that are available to the user. This is the important bit – if you don’t get this right, the sitemap provider will not work as expected. All nodes in your file must:

  1. Be wrapped in an overall parent node representing the home page of your website.
    After all, the homepage is always the first point of call into any web application
  2. Point to REAL controllers and REAL actions.
    If you fill up your MVC.sitemap file with dummy nodes pointing to non existent controllers and actions, MVC site provider will not return these nodes in any rendering of the sitemap. You will not get an error message, but will just not see your nodes.
  3. Not point to a controller and an action that is already pointed to by a previous node.
    Again, the MVC sitemap provider will just remove any duplicate instances at runtime. You will not get an error message, but will just not see your nodes.

Here is an example of an MVC.sitemap file that is in a good format and is readable to the MVC sitemap provider (apologies if the spacing has not worked correctly):

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
&lt;mvcSiteMap xmlns=&quot;; enableLocalization=&quot;false&quot;&gt;
  &lt;mvcSiteMapNode title=&quot;Home&quot; controller=&quot;Home&quot; action=&quot;Index&quot; changeFrequency=&quot;Always&quot; updatePriority=&quot;Normal&quot;&gt;
  &lt;mvcSiteMapNode title=&quot;Home&quot; controller=&quot;Home&quot; action=&quot;Test&quot; description=&quot;Home&quot;&gt;
  &lt;mvcSiteMapNode title=&quot;Dashboard&quot; controller=&quot;Home&quot; action=&quot;Dashboard&quot;/&gt;
  &lt;mvcSiteMapNode title=&quot;My Profile&quot; controller=&quot;Profile&quot; action=&quot;MyProfile&quot;/&gt;
  &lt;mvcSiteMapNode title=&quot;My Jobs&quot; controller=&quot;Profile&quot; action=&quot;MyJobs&quot;/&gt;
 &lt;mvcSiteMapNode title=&quot;Workplace&quot; controller=&quot;Workplace&quot; action=&quot;Index&quot; description=&quot;users&quot;&gt;
  &lt;mvcSiteMapNode title=&quot;Calendar&quot; controller=&quot;Workplace&quot; action=&quot;Calendar&quot;/&gt;
  &lt;mvcSiteMapNode title=&quot;Customers&quot; controller=&quot;Workplace&quot; action=&quot;Customers&quot;/&gt;
  &lt;mvcSiteMapNode title=&quot;Equipment&quot; controller=&quot;Workplace&quot; action=&quot;Equipment&quot;/&gt;

Now, all you need to do is get the call to display your menu correct. If you get this wrong, you will end up displaying nodes that you don’t want to display. Here’s the call that worked for me on a file in a Mvc.Sitemap file that is essentially the same as the code listing above. This is in Razor syntax:

@Html.MvcSiteMap().Menu(false, true, false)

This call is telling the MvcSiteMap to display a menu not starting from the current node (the page the client is currently viewing), starting from the first child node, and hiding the overall starting node. This call has worked for me, but you may wish to tweak it depending on what exactly you want.

I will shortly put up a post about customising the way that the MVC Sitemap provider displays a menu or breadcrumb trail.


A more in-depth tutorial is now available from here. It covers starting from scratch, displaying navigation, breadcrumbs, and customising their appearance.



Recommended Reading:

Pro ASP.NET MVC 3 Framework