I am developing an ASP.NET Core 8.0 application using Razor Pages. I have implemented a dynamic navigation menu that needs to be consistently displayed across all pages of my application. The navigation menu items are fetched dynamically based on the user’s role from a database.
I have successfully implemented a navigation menu using Razor Pages and I’m currently displaying it on a dedicated Main.cshtml page. However, when a user navigates to another page, the new page opens independently of the navigation menu, which I want to remain consistent across all pages.
Main.cshtml code:
<ul class="horizontal-list ">
@foreach (var menuItem in Model.MenuItems.Where(m => m.parentId == null))
{
<li>
<a class="dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">@menuItem.formName</a>
<ul class="dropdown-menu">
@foreach (var subMenuItem in Model.MenuItems.Where(m => m.parentId == menuItem.formID))
{
@if (Model.MenuItems.Any(m => m.parentId == subMenuItem.formID))
{
<li class="dropdown-submenu">
<a class="dropdown-item dropdown-toggle menutext" href="#">@subMenuItem.formName</a>
<ul class="dropdown-menu">
@foreach (var subsubMenuItem in Model.MenuItems.Where(m => m.parentId == subMenuItem.formID))
{
<li class="dropdown-menu-1">
<a class="dropdown-item menutext" href="@subsubMenuItem.formUrl">@subsubMenuItem.formName</a>
</li>
}
</ul>
</li>
}
else
{
<li class="dropdown-submenu">
<a class="dropdown-item menutext" href="@subMenuItem.formUrl">@subMenuItem.formName</a>
</li>
}
}
</ul>
</li>
}
</ul>
Main.cshtml.cs code:
public List<Menu> GetMenusForRole(long roleId)
{
var menuList = new List<Menu>();
// Example logic to fetch menus based on roleId from a database
ArrayList parameters = new ArrayList { roleId };
DataTable dtMenus = ExecuteStoredProcedure.ExecProc_getDataTable(_configuration, "Stored_Procedure_Name", parameters);
foreach (DataRow row in dtMenus.Rows)
{
menuList.Add(new Menu
{
formID = Convert.ToInt64(row["Form_ID"].ToString()),
formName = row["Form_Title"].ToString(),
parentId = row["Form_Parent_ID"] == DBNull.Value ? (long?)null : Convert.ToInt64(row["Form_Parent_ID"].ToString()),
formUrl = row["Form_Url"].ToString()
});
}
return menuList;
}
What I’ve Tried
Initially, I created a Main.cshtml and Main.cshtml.cs to display the navigation dropdowns, but this approach leads to the new pages opening independently.
I attempted to move the navigation bar into the _Layout.cshtml file, which is used as the main layout template across all pages. However, since the menu items are dynamically fetched based on user roles, I encountered difficulties because _Layout.cshtml does not directly support backend logic.
Desired Outcome:
I want to have a navigation menu that remains fixed across all pages of my application, where each menu item is dynamically fetched based on the user’s role. When a user navigates to a new page, I want this page to be displayed within the context of the navigation menu, without the menu itself being refreshed.
2
Answers
The recommendation for data-driven components that depend on backend logic and are intended for the layout page is a View Component.
The code from Main.cshtml will go into the component’s default.cshtml file, and the backend logic goes into the ViewComponent class file, which supports dependency injection.
you could try to place the navigation menu in the
_Layout.cshtml
file as it does not support backend logic, you will need to make use of a combination of dependency injection and a view component.Views/Shared/Components/NavigationMenu/Default.cshtml:
_Layout.cshtml: