Loading...
Area: Episerver CMS
Applies to versions: 11.21 and higher
Other versions:

Adding and configuring menu items

[MenuItem] attribute

Use MenuItem on ASP.NET MVC controllers. MenuItem adds links to the top menu (and requires the module to be registered; see Shell Modules). The required menuPath parameter is a logical path of the menu element in the menu. Use the Url parameter to add a linked URL to the interface.

The following example adds a menu item to the top menu bar with the text Start and the URL is inferred from the ASP.NET MVC route table:

public class DashboardController : Controller
{
  [MenuItem("/global/dashboard", Text = "Start")]
  public ActionResult Index()
  {
  }
}

When you have added menu items, you need to implement the new page to include Episerver's styling for shell and also render the menu so you can navigate back.

The key function to render a menu is:

  • @Html.Raw(Html.CreatePlatformNavigationMenu())

Note that the calls to Html.ShellInitializationScript() might still be needed depending on what content you are showing in addition to the navigation menu. It is not necessary for the navigation menu itself.

In addition to Html.CreatePlatformNavigationMenu, you also need to wrap content below the menu in an element decorated by using this html helper:

  • Html.ApplyPlatformNavigation()

Note: The Platform Navigation font sizing uses REM and expects the root element to have size 16px (browser default). Some style frameworks, such as Bootstrap 3, override the root font size while others, like Bootstrap 4, do not.

To adapt the example above to work with versions 11.21 and higher, you need to start using CreatePlatformNavigationMenu() and ApplyPlatformNavigation(). Note that you no longer need @Html.Raw(ClientResources.RenderResources("Navigation")) nor @Html.Raw(Html.ShellInitializationScript()):

@using EPiServer.Framework.Web.Resources
@using EPiServer.Shell.Navigation

<!DOCTYPE html>
<html>
  <head>
    <title>@ViewBag.Title</title>

    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />

    <!-- Shell -->
    @Html.Raw(ClientResources.RenderResources("ShellCore"))
    @Html.Raw(ClientResources.RenderResources("ShellWidgets"))

    <!-- LightTheme -->
    @Html.Raw(ClientResources.RenderResources( "ShellCoreLightTheme"))
 
    <!-- Dojo Dashboard -->
    @Html.Raw(ClientResources.RenderResources( "DojoDashboardCompatibility", new[] { ClientResourceType.Style }))
 
  </head>
  <body>
    @Html.Raw(Html.ShellInitializationScript())
    @Html.Raw(Html.CreatePlatformNavigationMenu())
    <div @Html.Raw(Html.ApplyPlatformNavigation())>
      @RenderBody()
    </div>
  </body>
</html>

Localizing menu items with the MenuItem attribute

You can localize menu items defined with attributes with a static property of a resource class. ResourceType references a class with a static property. TextResourceKey is the name of the static property that returns the localized text.

Example:

[MenuItem("/global/dashboard", TextResourceKey = "Start", ResourceType = typeof(MenuResources))]

Organizing menu items

The menu path is used to organize menu items in a tree structure. All menu items in the top menu are in the /global bucket. The next segment is the name of menu section, for example, /global/cms. The last segment represents the actual user interface, for example, /global/cms/edit.

Creating a link in a menu

Some menu items have a URL. This creates a link in the menu. The page at the end of this URL should render a menu where the corresponding menu path is selected.

Permissions with the MenuItem attribute

You can restrict who sees a certain menu item by using the [Authorize] attribute. For example:

public class DashboardController : Controller
{
  [MenuItem("/global/dashboard")]
  [Authorize(Roles = "NoOne")]
  public ActionResult Index()
  {
  }
}

Examples

Below you can find few examples of adding menu items.

  1. Global menu button

    using System.Web.Mvc;
    using EPiServer.Shell.Navigation;
    
    namespace Alloy.Business
    {
        public class EpiServerWorldGlobalMenuItem : Controller
        {
            [MenuItem(MenuPaths.Global + "/globalLink", SortIndex = SortIndex.First - 10, Text = "Episerver world",
                Url = "https://world.episerver.com/cms/")]
            public ActionResult Index(string viewName)
            {
                return View();
            }
        }
    }
  2. Extending the CMS menu section.

    using System.Collections.Generic;
    using EPiServer;
    using EPiServer.Security;
    using EPiServer.Shell.Navigation;
    
    namespace Alloy.Business
    {
        [MenuProvider]
        public class CmsMenuProvider : IMenuProvider
        {
            public IEnumerable<MenuItem> GetMenuItems()
            {
                var menuItems = new List<MenuItem>();
                menuItems.Add(new UrlMenuItem("Another link to Admin",
                    MenuPaths.Global + "/cms" + "/cmsMenuItem",
                    UriSupport.ResolveUrlFromUIAsRelativeOrAbsolute("Admin/Default.aspx"))
                {
                    SortIndex = SortIndex.First + 25,
                    IsAvailable = (request) => PrincipalInfo.HasAdminAccess
                });
    
                return menuItems;
            }
        }
    }
  3. Addng the second level menu.

    second-level-menu.png
    In the example below, a second level menu is added to the "Admin". Note that once the second level menu is added, the url of the first level item is invalid. When user click on first level item "Admin", it goes to the first item of its submenu automatically. Use this to group menu items when the first level has too many items to fit on the users screen.

    using System.Collections.Generic;
    using EPiServer;
    using EPiServer.Shell.Navigation;
    
    namespace Alloy.Business
    {
        [MenuProvider]
        public class LevelTwoMenuProvider : IMenuProvider
        {
            const string LevelTwoMenuPath = MenuPaths.Global + "/cms/admin";
    
            public IEnumerable<MenuItem> GetMenuItems()
            {
                var menuItems = new List<MenuItem>();
    
                menuItems.Add(new UrlMenuItem("CMS Admin", LevelTwoMenuPath + "/item1",
                    UriSupport.ResolveUrlFromUIAsRelativeOrAbsolute("Admin/Default.aspx"))
                );
    
                menuItems.Add(new UrlMenuItem("CMS blog", LevelTwoMenuPath + "/item2",
                    "https://world.episerver.com/blogs/?type=cmsblog&page=1")
                );
    
                menuItems.Add(new UrlMenuItem("Commerce blog", LevelTwoMenuPath + "/item3",
                    "https://world.episerver.com/blogs/?type=commerceblog&page=1")
                );
    
                return menuItems;
            }
        }
    }
    
  4. New global menu section.


    Please note that while the example below works, it is not recommended to use the main navigation for external links. A better example for external links could be example 6 below.

    using System.Collections.Generic;
    using EPiServer.Security;
    using EPiServer.Shell.Navigation;
    
    namespace Alloy.Business
    {
        [MenuProvider]
        public class GlbalSectionMenuProvider : IMenuProvider
        {
            const string MainMenuPath = MenuPaths.Global + "/customSection";
    
            public IEnumerable<MenuItem> GetMenuItems()
            {
                var menuItems = new List<MenuItem>();
    
                menuItems.Add(new SectionMenuItem("Episerver Forum", MainMenuPath)
                {
                    SortIndex = SortIndex.Last + 10,
                    IsAvailable = (request) => PrincipalInfo.HasEditAccess
                });
    
                menuItems.Add(new UrlMenuItem("CMS", MainMenuPath + "/item1",
                    "https://world.episerver.com/forum/developer-forum/-Episerver-75-CMS/")
                {
                    SortIndex = 1,
                });
    
                menuItems.Add(new UrlMenuItem("Commerce", MainMenuPath + "/item2",
                    "https://world.episerver.com/forum/developer-forum/Episerver-Commerce/")
                {
                    SortIndex = 2,
                });
    
                menuItems.Add(new UrlMenuItem("Forms", MainMenuPath + "/item3",
                    "https://world.episerver.com/forum/developer-forum/episerver-forms/")
                {
                    SortIndex = 3,
                });
    
                return menuItems;
            }
        }
    }
  5. Extending the User Settings menu using controller action.

    using System.Web.Mvc;
    using EPiServer.Shell.Navigation;
    
    namespace Alloy.Business
    {
        /// <summary>
        ///  Menu item under User Settings menu (menu added using using controller action)
        /// </summary>
        /// <returns></returns>
        public class EpiServerWorldMenuItem : Controller
        {
            [MenuItem(MenuPaths.UserSettings, SortIndex = SortIndex.First - 10, Text = "About Episerver",
                Url = "https://www.episerver.com/about/company/overview/")]
            public ActionResult Index(string viewName)
            {
                return View();
            }
        }
    }
  6. Extending the User Settings menu using menu provider.

    using System.Collections.Generic;
    using EPiServer.Shell.Navigation;
    
    namespace Alloy.Business
    {
        [MenuProvider]
        public class UserSettingsMenuProvider : IMenuProvider
        {
            public IEnumerable<MenuItem> GetMenuItems()
            {
                var menuItems = new List<MenuItem>();
                var item = new UrlMenuItem("Documentation", MenuPaths.User + "/episerver2",
                    "https://world.episerver.com/documentation/")
                {
                    SortIndex = SortIndex.Last + 10
                };
                menuItems.Add(item);
                return menuItems;
            }
        }
    }
  7. New drop-down menu with items.

    text-action-links.png

    using System.Collections.Generic;
    using EPiServer.Shell.Navigation;
    
    namespace Alloy.Business
    {
        [MenuProvider]
        public class DropdownMenuProvider : IMenuProvider
        {
            const string DropdownMenuPath = MenuPaths.Global + "/customDropdownMenu";
    
            public IEnumerable<MenuItem> GetMenuItems()
            {
                var menuItems = new List<MenuItem>();
    
                var userMenu = new DropDownMenuItem("Episerver blogs", DropdownMenuPath)
                {
                    SortIndex = SortIndex.Last - 20,
                    Alignment = MenuItemAlignment.Right
                };
                menuItems.Add(userMenu);
    
                menuItems.Add(new UrlMenuItem("CMS", DropdownMenuPath + "/item1",
                    "https://world.episerver.com/blogs/?type=cmsblog&page=1")
                {
                    SortIndex = 1,
                });
    
                menuItems.Add(new UrlMenuItem("Commerce", DropdownMenuPath + "/item2",
                    "https://world.episerver.com/blogs/?type=commerceblog&page=1")
                {
                    SortIndex = 2,
                });
    
                menuItems.Add(new UrlMenuItem("Find", DropdownMenuPath + "/item3",
                    "https://world.episerver.com/blogs/?type=findblog&page=1")
                {
                    SortIndex = 3,
                });
    
                return menuItems;
            }
        }
    }

Last updated: Sep 11, 2019