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.
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, useservices.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>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):
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
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 .Simply download the lib and copy the
simple-sidebar.css
towwwroot/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:
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
C# VS Java Enum (For Those New to C#)
Reading Email Using Pop3 in C#
Entity Framework Change Connection at Runtime
How to Make a .Net Windows Forms Application That Only Runs in the System Tray
How to Elevate Privileges Only When Required
Ignoring a Class Property in Entity Framework 4.1 Code First
How to Split a String with a String Delimiter
Call One Constructor from Another
How to Update Gui with Backgroundworker
How to Get a List of Users from Active Directory
Most Elegant Way to Generate Prime Numbers
Get a Screenshot of a Specific Application
Select N Random Elements from a List<T> in C#
Where to Learn About VS Debugger 'Magic Names'
Difference Between Console.Read() and Console.Readline()
How to Move Mouse Cursor Using C#