How to add a breadcrumb menu in Orchard Core - Orchard Core Nuggets

breadcrumb menu is a simple but effective navigation aid that shows the user where they are in the site's content structure and which path they can take back. It's also part of the web accessibility guidelines. However, there's no feature built into Orchard Core for this. Nevertheless, how to create a breadcrumb menu?

It's actually really easy, you just have to copy a piece of code from Orchard Dojo! Oh wait, we're Orchard Dojo. So here you go:


@inject OrchardCore.ContentManagement.IContentAliasManager ContentAliasManager;
@inject OrchardCore.ContentManagement.IContentManager ContentManager;
@inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor;

@using OrchardCore.ContentManagement;
@using OrchardCore.Menu.Models;

@{
    // Retrieving the menu we want to build the breadcrum menu for, in this case the one with the alias "main-menu".
    var menu = await ContentManager.GetAsync(await ContentAliasManager.GetContentItemIdAsync("alias:main-menu"));

    // We'll need the current URL to be able to check which menu item corresponds to the page.
    var currentRelativeUrl = HttpContextAccessor.HttpContext.Request.Path;

    var breadcrumbItems = new Stack<ContentItem>();

    // Building the path in the menu tree to the current item.
    bool SearchActiveItem(IEnumerable<ContentItem> menuItems)
    {
        if (menuItems == null) return false;

        // Note that for the sake of simplicity this will work only with Link Menu Items, not with Conten Menu Items.
        foreach (var menuItem in menuItems.Select(item => item.As<LinkMenuItemPart>()).Where(item => item != null))
        {
            if (!string.IsNullOrEmpty(menuItem.Url))
            {
                var url = menuItem.Url;
                if (url.StartsWith("~")) url = url.Substring(1);

                if (url.Equals(currentRelativeUrl, StringComparison.OrdinalIgnoreCase))
                {
                    breadcrumbItems.Push(menuItem.ContentItem);
                    return true;
                }
                else
                {
                    if (SearchActiveItem(menuItem.ContentItem.As<MenuItemsListPart>()?.MenuItems))
                    {
                        breadcrumbItems.Push(menuItem.ContentItem);
                        return true;
                    }
                }
            }
        }

        return false;
    }


    SearchActiveItem(menu.As<MenuItemsListPart>().MenuItems);
}

@* Using the Bootstrap breadcrumb classes. *@
<ul class="breadcrumb">
    <li class="breadcrumb-item">
        <a href="@Url.Content("~/")">@T["Home"]</a>
    </li>
    @while (breadcrumbItems.TryPop(out var menuItem))
    {
        var linkItem = menuItem.As<LinkMenuItemPart>();
        <li class="breadcrumb-item">
            <a href="@Url.Content(linkItem.Url)">@linkItem.Name</a>
        </li>
    }
</ul>

Wait, wait, slow a bit down. What is this?

This is the code that would render a simple breadcrumb menu for the menu with the alias "main-menu". If you've set up your Orchard site with any of the built-in recipes you already should have such a menu. But do take a look at the code in detail, we have a lot of helpful comments in there!

Once you're clear on what this piece of code does you can copy it somewhere in your theme to display it. For example, you can just put it into the Layout shape template. A cleaner approach would be to put it into its own separate template, like BreadcrumbMenu.cshtml, and display it in one of the many ways possible.

Pretty much that's it! Now let's suppose you built e.g. a menu like this:

A multi-level menu built in Orchard Core, as visible on the Orchard admin

With the above snippet you can have a breadcrumb menu like this when you open the Module Development page:

A breadcrumb menu displayed on the Orchard Core frontend, using the default Bootstrap styling

This just uses the default Bootstrap breadcrumbs styling.

And that's it, we're done with our breadcrumbs, enjoy! To be fair, this could use some work to make it bulletproof. We could e.g. optimize away the whole lookup when we're on the homepage. Then, it only supports only a single menu item for a given page. Nevertheless, it should get you going. If you'd like to see a generic and more advanced breadcrumb menu feature in Orchard check out this issue.

Did you like this post? It's part of our Orchard Core Nuggets series where we answer common Orchard questions, be it about user-facing features or developer-level issues. Check out the other posts for more such bite-sized Orchard Core tips and let us know if you have another question!