How to Create a Navigation Menu in Dotnet Application

How to create a navigation menu in dotnet application?

The short answer to doing what you want to do is that you simply can't.

Think about it: you are trying to have an interactive program (that users can interact with via the keyboard). But you are also making it a daemon (a deamon runs the background and doesn't interact with users directly). These are two contradictory goals.

When systemd (or supervisord, or upstart or really any system services program) runs your application as a service, it doesn't give it a way to interact with users, since these applications want to be daemons - which means users can't interact with them.

So, ask yourself what you want to do: do you want to make an interactive program or not? If you want make an interactive program you can't run it via supervisor. Run it directly, via dotnet /path/to/your.dll.

Other comments:

  • ReadKey may have issues, but certainly not in the common case that you are drying to do, which seems to be Linux on x86_64.

  • OmniSharp is a plugin for IDEs/text-editors to make development easier. It provides auto completion and real time syntax highlighting. It's not involved when you are running your application.

Adding a Dropdown menu to the NavBar in an ASP.Net Core Web App (bootstrap)

Be sure your Bootstrap version is v5.1, you can add the following css and js file to your project _Layout.cshtml:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.1/css/bootstrap.min.css" integrity="sha512-6KY5s6UI5J7SVYuZB4S/CZMyPylqyyNZco376NM2Z8Sb8OxEdp02e1jkKk/wZxIEmjQ6DRCEBhni+gpr9c4tvA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.1.1/js/bootstrap.min.js" integrity="sha512-ewfXo9Gq53e1q1+WDTjaHAGZ8UvCWq0eXONhwDuIoaH8xz2r96uoAYaQCm1oQhnBfRXrvJztNXFsTloJfgbL5Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

For Bootstrap v4.x, you need change your code to:

<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Dropdown
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</li>

Populate Navigation Bar based from Login using ASP.NET Core MVC

To populate the navigation menu, first, I suggest you create a NavigationModel model to store the navigation text and the url, the NavigationModel model as below:

public class NavigationModel
{
public int Id { get; set; }
public string NavigationName { get; set; }
public string NavigationUrl { get; set; }
public string PlanType { get; set; }
}

And the following DataRepository contains the test data, in your application, you could store the data into database, then get the navigations via the DbContext:

public class DataRepository : IDataRepository
{
public List<NavigationModel> GetNavigations()
{
return new List<NavigationModel>()
{
new NavigationModel(){ Id =1001, NavigationName="Orders", NavigationUrl="Home/Orders", PlanType="Plan1"},
new NavigationModel(){ Id =1002, NavigationName="Reprint Receipt", NavigationUrl="Home/Reprint", PlanType="Plan1"},
new NavigationModel(){ Id =1003, NavigationName="Report", NavigationUrl="Home/Report", PlanType="Plan1"},
new NavigationModel(){ Id =1004, NavigationName="Setting", NavigationUrl="Home/Setting", PlanType="Plan1"},
new NavigationModel(){ Id =1005, NavigationName="Orders", NavigationUrl="Home/Orders", PlanType="Plan2"},
new NavigationModel(){ Id =1006, NavigationName="Buy", NavigationUrl="Home/Buy", PlanType="Plan2"},
new NavigationModel(){ Id =1007, NavigationName="Report", NavigationUrl="Home/Report", PlanType="Plan2"},
new NavigationModel(){ Id =1008, NavigationName="Setting", NavigationUrl="Home/Setting", PlanType="Plan2"},
new NavigationModel(){ Id =1009, NavigationName="Orders", NavigationUrl="Home/Orders", PlanType="Plan3"},
new NavigationModel(){ Id =10010, NavigationName="Buy", NavigationUrl="Home/Buy", PlanType="Plan3"},
new NavigationModel(){ Id =10011, NavigationName="Cancel Purchase", NavigationUrl="Home/CancelPurchase", PlanType="Plan3"},
};
}
}

Then, you could try to use the following methods to populate the navigation menu.

  1. Use session to store the navigation information.

    First, configure the application to use session and add the SessionExtensions (Note the session expired time)

    Second, after user login successfully, you could refer the following code to get the relate navigation menu, and store them in the session:

     public IActionResult Index()
    {
    var isUserLogin = true;
    var plantype = "Plan2";

    if (isUserLogin && _dataRepository.GetNavigations().Any(c => c.PlanType.Contains(plantype)))
    {
    var navigations = _dataRepository.GetNavigations().Where(c => c.PlanType == plantype).ToList();

    if (HttpContext.Session.Get<List<NavigationModel>>("Navigation") == default)
    {
    HttpContext.Session.Set<List<NavigationModel>>("Navigation", navigations);
    }

    }
    return View();
    }

    In the _Layout.cshtml page, add the following code in the header:

     @using Microsoft.AspNetCore.Http
    @inject IHttpContextAccessor HttpContextAccessor

    [Note] In the Startup.ConfigureServices method, use services.AddHttpContextAccessor(); to register the HttpContextAccessor.

    Then, we could access the session and populate the navigation menu:

     <ul class="navbar-nav flex-grow-1">
    <li class="nav-item">
    <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
    </li>
    <li class="nav-item">
    <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
    </li>
    @if (HttpContextAccessor.HttpContext.Session.Get<List<NavigationModel>>("Navigation") != default)
    {
    var navigations = HttpContextAccessor.HttpContext.Session.Get<List<NavigationModel>>("Navigation");
    foreach (var item in navigations)
    {
    <li class="nav-item">
    <a class="nav-link text-dark" href="@item.NavigationUrl">@item.NavigationName</a>
    </li>
    }

    }
    </ul>
  2. Use JQuery Ajax to call the action method and populate the navigation menu:

    In the Home Controller, create an action method to get the navigation menu:

     [HttpPost]
    public IActionResult GetNavigation(string plantype)
    {
    //check if user login and get the relate navigation menus.
    return Json(_dataRepository.GetNavigations().Where(c => c.PlanType == plantype).ToList());
    }

    In the _Layout.cshtml page, use the following code to add the navigation menu:

     <ul class="navbar-nav flex-grow-1">
    <li class="nav-item">
    <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
    </li>
    <li class="nav-item">
    <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
    </li>
    </ul>

    <script>
    $(function () {
    $.ajax({
    url: "Home/GetNavigation",
    method: "Post",
    data: { "plantype": "Plan2" },
    success: function (items) {
    for (var i = 0; i < items.length; i++) {
    var li = document.createElement('li');
    li.setAttribute('class', 'nav-item');

    var a = document.createElement('a');
    a.setAttribute('class', 'nav-link text-dark');
    a.href = items[i].navigationUrl;
    var linkText = document.createTextNode(items[i].navigationName);
    a.appendChild(linkText);

    li.appendChild(a);

    $(".navbar-nav")[0].appendChild(li);
    }
    }
    })
    });
    </script>

The result as below (display plan 2):

Sample Image

How to create a hover drop down menu nav bar asp.net

Edit:
To further elaborate on where the below should go, and since we are talking about webforms here, you should open the Site.Master page.

In the Site.Master Page:
If you have left the default code that Visual Studio builds in, you should see the following lines between the <Scripts></Scripts> tags:

        <asp:ScriptReference Name="MsAjaxBundle" />
<asp:ScriptReference Name="jquery" />
<asp:ScriptReference Name="bootstrap" />
<asp:ScriptReference Name="respond" />
<asp:ScriptReference Name="WebForms.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebForms.js" />
<asp:ScriptReference Name="WebUIValidation.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebUIValidation.js" />
<asp:ScriptReference Name="MenuStandards.js" Assembly="System.Web" Path="~/Scripts/WebForms/MenuStandards.js" />
<asp:ScriptReference Name="GridView.js" Assembly="System.Web" Path="~/Scripts/WebForms/GridView.js" />
<asp:ScriptReference Name="DetailsView.js" Assembly="System.Web" Path="~/Scripts/WebForms/DetailsView.js" />
<asp:ScriptReference Name="TreeView.js" Assembly="System.Web" Path="~/Scripts/WebForms/TreeView.js" />
<asp:ScriptReference Name="WebParts.js" Assembly="System.Web" Path="~/Scripts/WebForms/WebParts.js" />
<asp:ScriptReference Name="Focus.js" Assembly="System.Web" Path="~/Scripts/WebForms/Focus.js" />
<asp:ScriptReference Name="WebFormsBundle" />

This tells us that jQuery and Bootstrap are being imported into the pages. JQuery is a JavaScript library that makes things a little easier. Bootstrap is a CSS library that makes it really easy to make things look good by adding a few classes to given elements.

By default, you will also see this in there as well:

  <div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" runat="server" href="~/">Application name</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a runat="server" href="~/">Home</a></li>
<li><a runat="server" href="~/About">About</a></li>
<li><a runat="server" href="~/Contact">Contact</a></li>
</ul>
</div>
</div>
</div>

That should look familiar as it is similar to the markup in your original post. To add a drop down list, compare the code below that includes a drop down and plug the needed parts into the above code. Something like this:

    <div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" runat="server" href="~/">Application name</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a runat="server" href="~/">Home</a></li>
<li><a runat="server" href="~/About">About</a></li>
<li><a runat="server" href="~/Contact">Contact</a></li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Page 4
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a runat="server" href="#">Page 1-1</a></li>
<li><a runat="server" href="#">Page 1-2</a></li>
<li><a runat="server" href="#">Page 1-3</a></li>
</ul>
</li>
</ul>
</div>
</div>
</div>

This should get your navbar and dropdown working when you click things.

Where to put the jQuery:
So, the best practice for any kind of external scripts, especially large ones, are to load them last, that way the page doesn't have to wait on them to load enough content to make the user happy. ASP.NET MVC does a much better job than Webforms does in this respect, but we can still try to do things correctly.

On the Site.Master page again, go all the way to the bottom. You're looking for the closing `' tag. Right before it, you'll need to put this:

<script>
$(document).ready(function () {
$(".dropdown").hover(function () {
//toggle the open class (on/off)
$(this).toggleClass("open");
});
})
</script>

So the end result would look like...:

... ... ...
... ... ...
<div class="container body-content">
<asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder>
<hr />
<footer>
<p>© <%: DateTime.Now.Year %> - My ASP.NET Application</p>
</footer>
</div>

</form>
<script>
//this line means we won't do anything until the page is ready for it
$(document).ready(function () {
$(".dropdown").hover(function () {
//toggle the open class (on/off)
$(this).toggleClass("open");
});
})
</script>
</body>
</html>

Before the edit:

Note: I'm making an assumption that you are using bootstrap and jQuery since this is tagged with asp.net and your original class names appear to be bootstrap syntax as well.

Here is a quick and easy way to accomplish this with bootstrap and jQuery:

jsfiddle: https://jsfiddle.net/tzv3t12c/9/

Bootstrap Nav Template:

<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">WebSiteName</a>
</div>
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<!-- This is the li that we want to manually modify on hover.
Basically, we're going to simulate the bootstrap event that happens
when the link is clicked. It doesn't do everything that bootstrap
does when the link is clicked, but it works easily in a pinch
-->
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Page 1
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Page 1-1</a></li>
<li><a href="#">Page 1-2</a></li>
<li><a href="#">Page 1-3</a></li>
</ul>
</li>
<li><a href="#">Page 2</a></li>
<li><a href="#">Page 3</a></li>

<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Page 4
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Page 1-1</a></li>
<li><a href="#">Page 1-2</a></li>
<li><a href="#">Page 1-3</a></li>
</ul>
</li>
</ul>
</div>
</nav>

Required jQuery:

//find elements with the dropdown class and attach the hover event to it
$(".dropdown").hover(function(){
//toggle the open class (on/off)
$(this).toggleClass("open");
});

Explanation:

Essentially, all I'm doing here is simulating the click actions that bootstrap performs when the dropdown link is clicked. If you use the developer tools in Chrome (or other browsers) by pressing F12, you can watch the HTML while you're interacting with the page. You'll notice that when the li with class dropdown is clicked, the open class gets added to it. There are some other elements that get changed as well and you might want to look into simulating those modifications too since changing the class on the dropdown li to dropdown open does not, even though it activates the transition.

Navigation menu on the left side with close and open button in ASP.NET Core razor pages application

  1. the simple-sidebar.css can be found on [GitHb(https://github.com/BlackrockDigital/startbootstrap-simple-sidebar) and official site . See the comment of the answer you posted above .

  2. Simply download the lib and copy thesimple-sidebar.css to wwwroot/lib/simple-sidebar/css/simple-sidebar.css .

and now you could add a link in you layout:

<link rel="stylesheet" href="~/lib/simple-sidebar/css/simple-sidebar.css">

simple-sidebar is a dead simple css lib which only requires your html structure in a conventional way.

<!-- your nav on top  -->
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<a asp-page="/Index" class="navbar-brand">Home</a>
<a asp-page="/Pinpad" class="navbar-brand">Pinpad</a>
</div>
</div>
</nav>

<div id="wrapper" class="toggled">

<!-- you nav on left side -->
<div id="sidebar-wrapper">
<a id="menu-toggle" href="#menu-toggle" class="btn btn-secondary">三</a>
<ul class="sidebar-nav"style="margin-top:15px;">
<li class="sidebar-brand">
<a asp-page="/Index" class="navbar-brand">Home</a>
</li>
<li>
<a asp-page="/Pinpad" class="navbar-brand">Pinpad</a>
</li>
</ul>
</div>

<!-- your main body here -->
<div id="page-content-wrapper">
<div class="container-fluid">
@RenderBody()
</div>
<footer></footer>
</div>
</div>

and add a style to show nav button and left side :

<style>
#wrapper #sidebar-wrapper{
width: 50px;
}

#wrapper .sidebar-nav{
display:none;
}

#wrapper.toggled .sidebar-nav{
display:block;
}

a#menu-toggle {
display:inline-block;
width: 100%;
line-height:100%;
padding:0;
margin:0;
color: dodgerblue;
}
</style>

At last , to toggle the sidebar , bind a function to handle the event :

$(document).ready(function () {
$("#menu-toggle").click(function (e) {
e.preventDefault();
$("#wrapper").toggleClass("toggled");
});
});

Here's a screenshot:

Sample Image

Here's the complete code list:

    <!DOCTYPE html>    <html>    <head>        <meta charset="utf-8" />        <meta name="viewport" content="width=device-width, initial-scale=1.0" />        <title>@ViewData["Title"] - Sample</title>            <link rel="stylesheet" href="~/lib/simple-sidebar/css/simple-sidebar.css">        <environment include="Development">            <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />            <link rel="stylesheet" href="~/css/site.css" />        </environment>        <environment exclude="Development">            <link rel="stylesheet"                  href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"                  asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"                  asp-fallback-test-class="sr-only" asp-fallback-test-                  property="position" asp-fallback-test-value="absolute" />            <link rel="stylesheet" href="~/css/site.min.css" asp-append-                  version="true" />        </environment>        <style>            #wrapper #sidebar-wrapper{                width: 50px;            }                #wrapper .sidebar-nav{                display:none;            }                #wrapper.toggled .sidebar-nav{                display:block;            }                a#menu-toggle {                display:inline-block;                width: 100%;                line-height:100%;                padding:0;                margin:0;                color: dodgerblue;            }        </style>    </head>    <body>        <nav class="navbar navbar-inverse navbar-fixed-top">            <div class="container">                <div class="navbar-header">                    <a asp-page="/Index" class="navbar-brand">Home</a>                    <a asp-page="/Pinpad" class="navbar-brand">Pinpad</a>                </div>            </div>        </nav>        <div id="wrapper" class="toggled">            <div id="sidebar-wrapper">                <a id="menu-toggle" href="#menu-toggle" class="btn btn-secondary">三</a>                <ul class="sidebar-nav"style="margin-top:15px;">                    <li class="sidebar-brand">                        <a asp-page="/Index" class="navbar-brand">Home</a>                    </li>                    <li>                        <a asp-page="/Pinpad" class="navbar-brand">Pinpad</a>                    </li>                </ul>            </div>                <div id="page-content-wrapper">                <div class="container-fluid">                    @RenderBody()                </div>                <footer></footer>            </div>        </div>            <environment include="Development">            <script src="~/lib/jquery/dist/jquery.js"></script>            <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>            <script src="~/js/site.js" asp-append-version="true"></script>        </environment>        <environment exclude="Development">            <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"                    asp-fallback-src="~/lib/jquery/dist/jquery.min.js"                    asp-fallback-test="window.jQuery"                    crossorigin="anonymous">            </script>            <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"                    asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"                    asp-fallback-test="window.jQuery && window.jQuery.fn &&     window.jQuery.fn.modal"                    crossorigin="anonymous">            </script>            <script src="~/js/site.min.js" asp-append-version="true"></script>        </environment>        <script>            $(document).ready(function () {                $("#menu-toggle").click(function (e) {                    e.preventDefault();                    $("#wrapper").toggleClass("toggled");                });            });        </script>            @RenderSection("Scripts", required: false)    </body>    </html>

Create ViewModel for Navigation

public class MenuContents
{
public IEnumerable<Products> AllProducts { get; set; }
public IEnumerable<Recepies> AllRecepies { get; set; }
public IEnumerable<Distributors> AllDistributors { get; set; }
public IEnumerable<Stores> AllStores { get; set; }

private XXXDb db = new XXXUSDb();

public void PopulateModel()
{
AllProducts = db.Products.ToList();
AllRecepies = db.Recepies.ToList();
AllDistributors = db.Distributors.ToList();
AllStores = db.Stores.ToList();
}
}

Then in your controller

public ActionResult PartialWhatever()
{
MenuContents model = new MenuContents();
model.PopulateModel();

return PartialView("PartialViewName", model);
}

Then in your partial view

@Model MenuContents

... do whatever here

In ASP.NET Core 2.1 how do I add menu items after the user has logged in based on Role?

After a little research into how the @await Html.PartialAsync("_LoginPartial") code works, I found a way to accomplish what I wanted. In the code below, from the _LoginPartial.cshtml file, I first verify that the User is logged in. Then, I check to see if the User is in a certain Role. If the User is in the specified Role I then emit the markup I want for that Role.

@inject SignInManager<ApplicationUser> SignInManager
@inject UserManager<ApplicationUser> UserManager

@if (SignInManager.IsSignedIn(User))
{
<form asp-controller="Account" asp-action="Logout" method="post" id="logoutForm" class="navbar-right">
<ul class="nav navbar-nav navbar-right">
<li>
<a asp-page="/ScheduleManagement/Scheduling">Schedule Shifts</a>
</li>
@if (User.IsInRole("AgencyAdministrator"))
{
<li>
<a asp-page="/ClientManagement/Index">Client Management</a>
</li>
<li>
<a asp-page="/ProjectManagement/Index">Project Management</a>
</li>
<li>
<a asp-page="/ShiftEmployeeManagement/Index">Shift Employee Management</a>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Types Management<span class="caret"></span></a>
<ul class="dropdown-menu">
<li>
<a asp-page="/TypeManagement/AddressType/Index">Address Type Management</a>
</li>
<li>
<a asp-page="/TypeManagement/DomainTypes/Index">Domain Type Management</a>
</li>
<li>
<a asp-page="/TypeManagement/EmailType/Index">Email Type Management</a>
</li>
<li>
<a asp-page="/TypeManagement/SkillLevelType/Index">Skill Level Type Management</a>
</li>
<li>
<a asp-page="/TypeManagement/SkillType/Index">Skill Type Management</a>
</li>
</ul>
</li>
}


Related Topics



Leave a reply



Submit