Extend menu from level two to three level in asp.net MVC - c#

I'm able to make just two level Menu from database How can I make it up to three level or more
I've seen a lot of tutorials but they all are to much of complex
Here is what I've done so far
My Action
public ActionResult SideMenu()
{
ViewBag.MenuLevelTest = Db
.Menus
.Where(menu => menu.ParentId == null)
.ToList();
return PartialView("_SideMenu");
}
My View
<ul class="page-sidebar-menu page-header-fixed page-sidebar-menu-hover-submenu " data-keep-expanded="false" data-auto-scroll="true" data-slide-speed="200">
#foreach (var menuLevelTest in ViewBag.MenuLevelTest)
{
<li class="nav-item start">
<a href="javascript:;" class="nav-link nav-toggle">
<i class="icon-home"></i>
<span class="title">#menuLevelTest.Name</span>
<span class="arrow"></span>
</a>
#if (menuLevelTest.Menu1.Count > 0)
{
<ul class="sub-menu">
#foreach (var menuLevelTest2 in menuLevelTest.Menu1)
{
<li class="nav-item start ">
<a href="index.html" class="nav-link ">
<i class="icon-bar-chart"></i>
<span class="title">#menuLevelTest2.Name</span>
</a>
</li>
}
</ul>
}
</li>
}
</ul>
I've tried to extend it by doing this but it does not work, what is the easiest way to make this happen
<ul class="page-sidebar-menu page-header-fixed page-sidebar-menu-hover-submenu " data-keep-expanded="false" data-auto-scroll="true" data-slide-speed="200">
#foreach (var menuLevelTest in ViewBag.MenuLevelTest)
{
<li class="nav-item start">
<a href="javascript:;" class="nav-link nav-toggle">
<i class="icon-home"></i>
<span class="title">#menuLevelTest.Name</span>
<span class="arrow"></span>
</a>
#if (menuLevelTest.Menu1.Count > 0)
{
<ul class="sub-menu">
#foreach (var menuLevelTest2 in menuLevelTest.Menu1)
{
<li class="nav-item">
<a href="javascript:;" class="nav-link nav-toggle">
<i class="icon-bar-chart"></i>
<span class="title">#menuLevelTest2.Name</span>
</a>
#if (menuLevelTest.Menu2.Count > 0)
{
<ul class="sub-menu">
#foreach (var menuLevelTest3 in menuLevelTest.Menu2)
{
<li class="nav-item">
<a href="javascript:;" class="nav-link nav-toggle">
<i class="icon-bar-chart"></i>
<span class="title">#menuLevelTest3.Name</span>
</a>
</li>
}
</ul>
}
</li>
}
</ul>
}
</li>
}
</ul>

This is how I Achieved the three levels
Created a BaseController
got the list of All menus
public BaseController()
{
ViewBag.Menu = MenuList();
}
private IList<Menu> MenuList()
{
var list = Db.Menus.ToList();
return list;
}
Here is my Razor for partial View
#{
List<MisNew.Web.EntityModel.Menu> menuList = ViewBag.Menu;
}
<ul class="menu page-sidebar-menu page-header-fixed page-sidebar-menu-hover-submenu " data-keep-expanded="false" data-auto-scroll="true" data-slide-speed="200">
#foreach (var mp in menuList.Where(p => p.ParentId == null))
{
<li class="#mp.ListCss">
<a href="#" class="#mp.HyperLinkCss">
<i class="#mp.IconCss"></i>
<span class="title">#mp.Name</span>
<span class="arrow"></span>
</a>
#if (menuList.Count(p => p.ParentId == mp.Id) > 0)
{
#:<ul class="sub-menu">
}
#RenderMenuItem(menuList, mp)
#if (menuList.Count(p => p.ParentId == mp.Id) > 0)
{
#:</ul>
}
</li>
}
</ul>
#helper RenderMenuItem(List<MisNew.Web.EntityModel.Menu> menuList, MisNew.Web.EntityModel.Menu mi)
{
foreach (var cp in menuList.Where(p => p.ParentId == mi.Id))
{
#:<li class="#cp.ListCss">
<a href="~/#cp.Url">
<i class="#cp.IconCss"></i>
<span class="title">#cp.Name</span>
<span class="arrow"></span>
</a>
if (menuList.Count(p => p.ParentId == cp.Id) > 0)
{
#:<ul class="sub-menu">
}
#RenderMenuItem(menuList, cp)
if (menuList.Count(p => p.ParentId == cp.Id) > 0)
{
#:</ul>
}
else
{
#:</li>
}
}
}

Related

Passing selected item data to controller from Multilevel dropdown

I have created a multilevel dropdown which is dynamic. When I am clicking the third level item(new, in progress, resolved which are from the database)it should be selected and only when I am clicking the create button that selected item data should be passed to the controller.
multilevel dropdown code
<div class="dropdown drop">
<button class="btn dropdown-toggle"
type="button"
id="dropdownMenuButton"
data-mdb-toggle="dropdown"
aria-expanded="false">
STATUS
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<li>
<a class="dropdown-item" href="#">
ProjectStatus »
</a>
<ul class="dropdown-menu dropdown-submenu">
#foreach (var i in ViewBag.ProjectStatus)
{
<li>
#*<a id="ProjectStatus" class="dropdown-item" href="#">#i.Text</a>*#
<select asp-for="ProjectStatus" class="form-control" value="#i.Text">#i.Text</select>
</li>
}
</ul>
</li>
<li>
<a class="dropdown-item" href="#">
DevelopmentStatus »
</a>
<ul class="dropdown-menu dropdown-submenu">
#foreach (var i in ViewBag.DevelopmentStatus)
{
<li>
<a class="dropdown-item" href="#">#i.Text</a>
</li>
}
</ul>
</li>
</ul>
</div>
HttpGet create method
public IActionResult Create()
{
ViewBag.ProjectStatus = new SelectList(_context.ProjectStatus, "ProjectStatusID", "Status");
ViewBag.DevelopmentStatus = new SelectList(_context.DevelopmentStatus, "DevelopmentStatusID", "Status");
return View();
}
Need to get the selected list item data to the post method
[HttpPost]
public async Task<IActionResult> Create(Projects ec) {}
You can try to put the selected item value to a hidden input,and then change the background of the <li></li>.Here is a demo:
<div class="dropdown drop">
<button class="btn dropdown-toggle"
type="button"
id="dropdownMenuButton"
data-mdb-toggle="dropdown"
aria-expanded="false">
STATUS
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<li>
<a class="dropdown-item" href="#">
ProjectStatus »
</a>
<ul class="dropdown-menu dropdown-submenu">
#foreach (var i in ViewBag.ProjectStatus)
{
<li>
<a class="dropdown-item" href='#' onclick='return change("#i.Text",this,"ProjectStatus")'>#i.Text</a>
</li>
}
</ul>
</li>
<li>
<a class="dropdown-item" href="#">
DevelopmentStatus »
</a>
<ul class="dropdown-menu dropdown-submenu">
#foreach (var i in ViewBag.DevelopmentStatus)
{
<li>
<a class="dropdown-item" href='#' onclick='return change("#i.Text",this,"DevelopmentStatus")'>#i.Text</a>
</li>
}
</ul>
</li>
</ul>
</div>
<input id="ProjectStatus" name="ProjectStatus" hidden />
<input id="DevelopmentStatus" name="DevelopmentStatus" hidden />
<script>
function change(text, t, type) {
$("li").css("background", "transparent");
if (type == "ProjectStatus") {
$("#ProjectStatus").val(text);
$("#DevelopmentStatus").val("");
} else {
$("#DevelopmentStatus").val(text);
$("#ProjectStatus").val("");
}
$(t).parent().css("background", "#1266f1");
return false;
}
</script>
When select ProjectStatus,the selected value will be put to $("#ProjectStatus"),and the value of $("#DevelopmentStatus") will be "".When select DevelopmentStatus,the selected value will be put to $("#DevelopmentStatus"),and the value of $("#ProjectStatus") will be "".
result:

How to add parameters in url.content

I try create dynamic menu but i have problem with adding parameters in link to the controller and action, can i add parameter to url.content? or there are the other way please give your insight it will very helpfull
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">Menu Example</a>
</div>
<ul class="nav navbar-nav">
#if (Session["Menu"] != null)
{
var MenuMaster = (List<Accountstatement.Models.MenuModel>)Session["Menu"];
var groupByMenu = MenuMaster.GroupBy(x => x.MainMenuName).ToList();
foreach (var MenuList in groupByMenu)
{
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">#MenuList.Key<span class="caret"></span></a>
<ul class="dropdown-menu">
#foreach (var SubMenuList in MenuList)
{
<li>#SubMenuList.SubMenuName</li>
}
</ul>
</li>
}
}
</ul>
this is the part the url.content is, how can i put the parameter inside url.content?
<li>#SubMenuList.SubMenuName</li>
Use #Html.Raw with Url.Content and pass parameters like below:
#Html.Raw(Url.Content("~/"+#SubMenuList.ControllerName +"/"+ #SubMenuList.ActionName?param=" + param.value))

The Aspnet.core program logs in but considers the data in the same table

I'm having a problem with the code, the program logs in and out
I have three controllers for each type of user, when I log in the program logs in but the presentation is as if they were all from the Socio table.
I already checked the tables and don't have the same data and I checked the layout of the views for each type of user and everything is fine.
Can someone help me fix this please?
The login method is in the controller home, and this is the code:
public IActionResult Login(string user, string password, string? ReturnUrl)
{
SHA512 sha512 = SHA512Managed.Create();
byte[] bytes = sha512.ComputeHash(Encoding.UTF8.GetBytes(password), 0, Encoding.UTF8.GetByteCount(password));
string passHash = Convert.ToBase64String(bytes);
Socios socio = _context.Socios.Include(s => s.Gerir).Include(s => s.Mensagem).Include(s => s.Participa).Include(s => s.PersonalTrainer).Include(s => s.Peso).Include(s => s.PlanosExercicios).FirstOrDefault(s => s.NomeUtilizador == user && s.Password == password);
if (socio != null)
{
HttpContext.Session.SetString("Nome", socio.NomeUtilizador);
HttpContext.Session.SetInt32("UserId", socio.Idsocio);
HttpContext.Session.SetString("Perfil", "Socio");
}
Professores prof = _context.Professores.Include(p => p.MapaAulasGrupo).Include(p => p.Mensagem).Include(p => p.Peso).Include(s => s.PersonalTrainer).Include(p => p.PlanosExercicios).FirstOrDefault(p => p.Nome == user && p.Password == password);
if (prof != null)
{
HttpContext.Session.SetString("Nome", prof.Nome);
HttpContext.Session.SetInt32("UserId", prof.Idprofessor);
HttpContext.Session.SetString("Perfil", "Professor");
}
Administrador admin = _context.Administrador.Include(a => a.Gerir).SingleOrDefault(a => a.Nome == user && a.Password == password);
if (admin != null)
{
HttpContext.Session.SetString("Nome", admin.Nome);
HttpContext.Session.SetInt32("UserId", admin.Idadministrador);
HttpContext.Session.SetString("Perfil", "Administrador");
}
if (String.IsNullOrEmpty(ReturnUrl))
{
//ModelState.AddModelError("","Utilizador inexistente na base de dados!");
//TempData["mensagemErro"] = "Utilizador inexistente na base de dados!";
//return View("NaoEncontrado","Socios");
return LocalRedirect("/");
}
else
{
return LocalRedirect(ReturnUrl);
}
}
In the layout I have to differentiate the type of logins, presenting views corresponding to each controller
<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-dark bg-dark border-bottom box-shadow mb-3">
<div class="container">
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index"> </a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
<ul class="navbar-nav">
#if (SociosController.estaAutenticado(Context))
{
<li class="nav-item">
<a class="nav-link text-white" asp-controller="Socios" asp-action="PerfilSocio">Meu perfil</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" asp-controller="Socios" asp-action="ListarProfessores">Professores</a>
</li>
<li class="nav-item">
<p class="nav-link text-white">Bem-vindo, #Context.Session.GetString("Nome")</p>
</li>
<li class="nav-item">
<form class="form-inline" asp-controller="Home" asp-action="Logout">
<button type="submit" class="nav-link btn btn-link text-white">Sair</button>
</form>
</li>
}
else if (ProfessoresController.estaAutenticado(Context))
{
<li class="nav-item">
<a class="nav-link text-white" asp-controller="Professores" asp-action="Perfil">Meu perfil</a>
</li>
<li class="nav-item">
<p class="nav-link text-white">Bem-vindo, #Context.Session.GetString("Nome")</p>
</li>
<li class="nav-item">
<form class="form-inline" asp-controller="Home" asp-action="Logout">
<button type="submit" class="nav-link btn btn-link text-white">Sair</button>
</form>
</li>
}
else if (AdministradoresController.estaAutenticado(Context))
{
<li class="nav-item">
<a class="nav-link text-white" asp-controller="Administradores" asp-action="Perfil">Meu perfil</a>
</li>
<li class="nav-item">
<p class="nav-link text-white">Bem-vindo, #Context.Session.GetString("Nome")</p>
</li>
<li class="nav-item">
<form class="form-inline" asp-controller="Home" asp-action="Logout">
<button type="submit" class="nav-link btn btn-link text-white">Sair</button>
</form>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-white" asp-controller="Home" asp-action="Login">Entrar </a>
</li>
<li class="nav-item">
<a class="nav-link text-white" asp-area="" asp-controller="Home" asp-action="Registo">Registar</a>
</li>
}
</ul>
<ul class="navbar-nav flex-grow-1">
<li class="nav-item">
<a class="nav-link text-white" asp-area="" asp-controller="Home" asp-action="Index">Pagina Inicial</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" asp-area="" asp-controller="Home" asp-action="Info">Sobre nós</a>
</li>
<li class="nav-item">
<a class="nav-link text-white" asp-area="" asp-controller="Home" asp-action="AulasDeGrupo">Aulas de Grupo</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
The function that calls in the layout "estaAutenticado"
is found in the Controllers of each type of user and this is the code:
public static bool estaAutenticado(HttpContext contexto)
{
if (contexto.Session.GetInt32("UserId") != null)
return true;
else
return false;
}
Can someone help me fix this? I don’t understand why he considers all users I log in as a Partner, even if they’re from the Teacher or Administrator tables.
The issue is you set the same Session-key UserId for each type of user , you should make the modification like below:
Login method
Socios socio = _context.Socios.Include(s => s.Gerir).Include(s => s.Mensagem).Include(s => s.Participa).Include(s => s.PersonalTrainer).Include(s => s.Peso).Include(s => s.PlanosExercicios).FirstOrDefault(s => s.NomeUtilizador == user && s.Password == password);
if (socio != null)
{
HttpContext.Session.SetString("Nome", socio.NomeUtilizador);
HttpContext.Session.SetInt32("UserId", socio.Idsocio);
HttpContext.Session.SetString("Perfil", "Socio");
}
Professores prof = _context.Professores.Include(p => p.MapaAulasGrupo).Include(p => p.Mensagem).Include(p => p.Peso).Include(s => s.PersonalTrainer).Include(p => p.PlanosExercicios).FirstOrDefault(p => p.Nome == user && p.Password == password);
if (prof != null)
{
HttpContext.Session.SetString("Nome", prof.Nome);
//set ProfessorId for Professores
HttpContext.Session.SetInt32("ProfessorId", prof.Idprofessor);
HttpContext.Session.SetString("Perfil", "Professor");
}
Administrador admin = _context.Administrador.Include(a => a.Gerir).SingleOrDefault(a => a.Nome == user && a.Password == password);
if (admin != null)
{
HttpContext.Session.SetString("Nome", admin.Nome);
//set AdminId for Administrador
HttpContext.Session.SetInt32("AdminId", admin.Idadministrador);
HttpContext.Session.SetString("Perfil", "Administrador");
}
estaAutenticado method in each type Controller
//SociosController
public static bool estaAutenticado(HttpContext context)
{
if (context.Session.GetInt32("UserId") != null)
return true;
else
return false;
}
//ProfessoresController
public static bool estaAutenticado(HttpContext context)
{
if (context.Session.GetInt32("ProfessorId") != null)
return true;
else
return false;
}
//AdministradoresController
public static bool estaAutenticado(HttpContext context)
{
if (context.Session.GetInt32("AdminId") != null)
return true;
else
return false;
}

ASP.Net MVC 5 Check User Role For _Layout

Hello everyone I am trying to check what Role my user is in with the default setup.
I thought I would only need 'User.IsInRole("User")' for in my View but its not so easy.
I want to display certain links depending on the role for the user.
Here is what I have and I tried a few different options.
I have the default setup database and some added tables that dont matter for this part.
Request.IsAuthenticated works for login.
I tried user.isinrole and request.isauthenticated but nether worked for this instance with my view
#if (Request.IsAuthenticated)
{
<li class="nav-item">
<a class="nav-link" href="#">Assign Roles</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">View Roles</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Reset Password</a>
</li>
} else if (Request.IsAuthenticated && User.IsInRole("User"))
{
<li class="nav-item">
<a class="nav-link" href="#">user Else clause</a>
</li>
} else if (Request.IsAuthenticated && User.IsInRole("Guest"))
{
<li class="nav-item">
<a class="nav-link" href="#">guest Else clause</a>
</li>
} else
{
<li class="nav-item">
<a class="nav-link" href="#">else else!! Else clause</a>
</li>
}
The 'else' works when no user is logged in.
You can add extension method for Principal like this
public static class PrincipalExtensions
{
public static bool IsInAllRoles(this IPrincipal principal, params string[] roles)
{
return roles.All(r => principal.IsInRole(r));
}
public static bool IsInAnyRoles(this IPrincipal principal, params string[] roles)
{
return roles.Any(r => principal.IsInRole(r));
}
}
And use
// user must be assign to all of the roles
if(User.IsInAllRoles("Admin","Manager","YetOtherRole"))
{
// do something
}
Read more at Usage of User.IsInRole() in a View
This is what I ended up doing to for my solution
#if (User.IsInRole("User"))
{
<li class="nav-item">
<a class="nav-link" href="#">user Else clause</a>
</li>
}
#if (User.IsInRole("Guest"))
{
<li class="nav-item">
<a class="nav-link" href="#">guest Else clause</a>
</li>
}

Set a page Item Active or Disable with bootstrap 4 pagination, using ASP.NET

I used this code with bootstrap 3, and it worked correctly, when clicking on the page, it appeared as active, but when switching to bootstrap 4, it no longer calls the active class, when I pass the page number inside the "for"
Any ideias how to resolve that?
<ul class="pagination">
<li class="page-item ">
#{
if (ViewBag.pageNumber> 1)
{
<a class="page-link" href="#Url.Action("Index", "Barcos", new { search= ViewBag.Search, pageNumber= ViewBag.pageNumber- 1 })">before</a>
}
else
{
<a class="page-link" href="#">
before
</a>
}
}
</li>
#{
var page = ViewBag.pageNumber;
for (var i = 1; i <= ViewBag.Count; i++)
{
<li #(page== i ? "class=page-item active" : "")>
<a class="page-link" href="#Url.Action("Index", "Barcos", new {search= ViewBag.Search, pageNumber= i})">#i</a>
</li>
}
}
<li>
#if (ViewBag.pageNumber< ViewBag.count)
{
<a class="page-link" href="#Url.Action("Index", "Barcos", new { Search= ViewBag.Search, pageNumber= ViewBag.pageNumber+ 1 })">Next</a>
}
else
{
<a class="page-link disabled" href="#">
Before
</a>
}
</li>
</ul>
You need class="page-item" on all list items, not just for your current page
Corrected bode below.
#for (var i = 1; i <= ViewBag.Count; i++)
{
var page = ViewBag.pageNumber;
string classes = "page-item";
if (page == i)
{
classes += " active";
}
<li class="#classes">
#Html.ActionLink(i.ToString(), "Index", "Barcos", new { search = ViewBag.Search, pageNumber = i }, new { #class = "page-link" })
</li>
}
This generates the following HTML
<ul class="pagination">
<li class="page-item ">
<a class="page-link" href="/Barcos/Index?pageNumber=1">before</a>
</li>
<li class="page-item">
<a class="page-link" href="/Barcos/Index?pageNumber=1">1</a>
</li>
<li class="page-item active">
<a class="page-link" href="/Barcos/Index?pageNumber=2">2</a>
</li>
<li class="page-item">
<a class="page-link" href="/Barcos/Index?pageNumber=3">3</a>
</li>
<li>
<a class="page-link" href="/Barcos/Index?pageNumber=4">Next</a>
</li>
</ul>

Categories