Managing breadcrumbs in ASP.NET core using SmartBreadcrumbs

Adding breadcrumbs to a website seems like an easy task and honestly, it should be. Unfortunately it's not, unless you want to end up copying the almost-same code in all your pages.

Today I'll be talking about how to add and manage breadcrumbs in an ASP.NET Core website using SmartBreadcrumbs (1.3.0), a library I created to help me add and manage breadcrumbs easily in my projects.

What are breadcrumbs and why use them

A breadcrumb is a type of secondary navigation that shows a user's current location in the website as well as the “history” of how he got there.

If your website has hierarchically arranged pages or is starting to have a lot of pages (e.g. e-commerce websites), Breadcrumbs can enhance the users navigation by a lot, reducing even the number of actions/clicks it takes them to do so.

Why isn't it simple to add them in ASP.NET Core

Adding breadcrumbs to ASP.NET Core isn't easy because there is no out-of-the-box solution. Which leaves 2 options:

  1. Manually adding them in every page.
  2. Using an external library to do so.

Manually adding them in every page

This option shouldn't and will not be considered because the purpose is to find a better way to handle breadcrumbs, not for us to manually add them every time.

Using an external library

This seems like a better solution, all we have to do is find THE library.

When I was making some websites for a client, I looked for a library that could help me add breadcrumbs to them without a lot of work.

I stumbled upon 2 interesting options:

  1. MvcSiteMapProviders is a tool that provides flexible menus, breadcrumb trails and SEO features for the ASP.NET MVC framework.
    As you might have noticed, it's only for ASP.NET MVC (v3 and v4) and won't work for ASP.NET v5 / Core.
  2. DNTBreadCrumb.Core creates custom breadcrumb definitions, based on Twitter bootstrap 3.x features for ASP.NET Core. I was happy when I found this library, until I tested it in my projects. DNBreadCrumb.Core works well with simple websites but not with more complex websites, because it doesn't handle breadcrumb items coming from different Controllers (at least not out of the box, if I understood correctly), which is a downside for me since I needed that kind of navigation.

So after not finding what I was looking for, I ended up creating my own simple utility library: SmartBreadcrumbs.

About SmartBreadcrumbs

Illustration of SmartBreadcrumbs

Illustration of SmartBreadcrumbs

SmartBreadcrumbs is a .NET Core utility library for ASP.NET Core websites to easily add and customize breadcrumbs. It is easy to setup and even easier to use!

How it works

At initialization, SmartBreadcrumbs will create a node hierarchy using all the breadcrumb attributes used on Actions (taken from all the Controllers in your Assembly).

You'll then be able to use a TagHelper that will check if the current action/controller has a node and will render the breadcrumb element if found.

By default, SmartBreadcrumbs uses Bootstrap 4's classes to style the breadcrumbs.

Usage

SmartBreadcrumbs is available on Nuget, you can install it directly from the Package Manager or using the console.

Initialization

In your services configuration, add:

csharp services.UseBreadcrumbs(GetType().Assembly);

This will let SmartBreadcrumbs extract all the Breadcrumb attributes and their Controller.Action and create a node hierarchy of them.

If you want to customize the css classes, you can do so using the options parameter:

// These are the classes by default (Bootstrap 4.1)
services.UseBreadcrumbs(GetType().Assembly, options =>
{
 TagName = "nav";
 TagClasses = "";
 OlClasses = "breadcrumb";
 LiClasses = "breadcrumb-item";
 ActiveLiClasses = "breadcrumb-item active";
 SeparatorElement = "<li class=\"separator\">/</li>";
});

The SeperatorElement will be added after each node, use it when you're using a custom theme/template for example.

Adding nodes

First, you'll need a Default node, most of the time (if not always) this will be your Home page.

The default node will always be present as the parent, even if not explicitly chosen.

[DefaultBreadcrumb("My home")]
public IActionResult Index()
{
 // We set the Home.Index as the default node
 // "My home" is the title that the node will use
 return View();
}

You can then start adding child nodes:

[Breadcrumb("About us")]
public IActionResult AboutUs()
{
 // In this case, the DefaultNode will be the parent of this node.
 return View();
}

[Breadcrumb("Contact us", FromAction = "Home.AboutUs")]
public IActionResult ContactUs()
{
 // This page is a child of the About us page
 return View();
}

You can even use the ViewData in case you want your titles to be taken from it:

[Breadcrumb("ViewData.Title")]
[Breadcrumb("ViewData.Title", CacheTitle = true)]
public IActionResult AboutUs()
{
 // In this case, the DefaultNode will be the parent of this node.
 return View();
}

Manually setting the current nodes

In some cases, you'll like to set the current nodes yourself. For example, you want the titles of more than one node to be taken from the database or some other source.

Luckily, SmartBreadcrumbs can trust you on this:

public IActionResult Product(int id)
{
 var product = GetProduct(id);

 // Manually create the nodes (assuming you used the attribute to create a Default node, otherwise create it manually too).
 var categoryNode = new BreadcrumbNode(product.Category.Name, "Controller", "Category", null, new { id = 10 });
 // When manually creating nodes, you have the option to use route values in case you need them.
 var productNode = new BreadcrumbNode(product.Title, "Controller", "Product", categoryNode);

 // All you have to do now is tell SmartBreadcrumbs about this
 ViewData["BreadcrumbNode"] = productNode; // Use the last node

 return View();
}

This is an e-commerce example where the result would be something like this: Home / Laptops / New ACER laptop

Rendering the breadcrumb

When you're finished adding all the nodes, the last step is to make use of the TagHelper to render the breadcrumb element:

<breadcrumb></breadcrumb>
@* In your _Layout.cshtml *@

Don't forget to import SmartBreadcrumbs:

@addTagHelper *, SmartBreadcrumbs
@* In your _ViewImports.cshtml *@

Conclusion

Breadcrumbs can be very helpful in some situations and to be able to add and manage easily can save you a lot of work/time and keeps your code clean.

This is why I created SmartBreadcrumbs, which I now use in every project (when needed of course).

Zanid Haytam Written by:

Zanid Haytam is an enthusiastic programmer that enjoys coding, reading code, hunting bugs and writing blog posts.