'Using Asp.Net Core Viewbag
Layout.cshtml
@{
var menus = (IEnumerable<WebApplication.Models.TopMenu>)ViewBag.menus;
}
<div class="col-md-8">
<!-- Menu Partial -->
@await Html.PartialAsync("~/Views/MainPage/TopMenu.cshtml", menus);
</div>
MainPageController.cs:
public IActionResult Mainpage()
{
ViewBag.menus = db.TopMenu.Where(a => a.Active).OrderBy(a => a.Order);
return View();
}
TopMenu.cshtml:
@{
Layout = null;
}
@model IEnumerable<WebApplication.Models.TopMenu>
<ul id="nav" class="sf-menu" >
<li><a href="#">MainPage</a></li>
@{
foreach (var item in Model)
{
<li>
@if (item.ParentId == null && Model.Where(a => a.ParentId == item.Id).Any())
{
<a href="/PageDetail/@[email protected]">@item.Name</a>
}
else if (item.ParentId == null && Model.Where(a => a.ParentId != item.Id).Any())
{
var link = "";
if (!String.IsNullOrEmpty(item.Link)) { link = item.Link; }
else { link = "/PageDetail" + item.Name + "-" + item.Id; }
<a href="@link">@item.Name</a>
}
<ul>
@foreach (var item1 in Model.Where(a => a.ParentId == item.Id))
{
<li><a style="text-transform:none;" href="/PageDetail/@[email protected]" >@item.Name</a></li>
}
</ul>
</li>
}
}
</ul>
I'm trying to show the top menu names from using database . Doesn't work and doesn't give an error.I tried to migrate with view bag and I am using ms sql. What should i do to get the menu names?
THE OTHER WAY
MainPageController.cs
public IActionResult MainPage()
{
// ViewBag.cars = db.Cars.OrderByDescending(a => a.date).Take(6);//view bag works for cars
var cars = db.Cars.OrderByDescending(a => a.date).Take(11);//it works this way too
//ViewBag.menus = db.TopMenu.Where(a => a.Active).OrderBy(a => a.Order).ToList();
return View(cars);
}
public IActionResult Menu() {
var menus = db.TopMenu.OrderByDescending(a => a.Active).OrderBy(a => a.Order);
return View(menus);
}
note: cars data works fine
_Layout.cshtml:
<div class="col-md-8">
<!-- Menu Partial -->
@await Html.PartialAsync("~/Views/MainPage/TopMenu.cshtml");
</div>
TopMenu.cshtml
THE OTHER WAY View COMPONENT
TopMenuViewComponent.cs
namespace WebApplication.ViewComponents
{
[ViewComponent(Name = "TopMenu")]
public class TopMenuViewComponent : ViewComponent
{
private readonly WebApplicationContext _context;
public TopMenuViewComponent(WebApplicationContext context)
{
_context = context;
}
public async Task<IViewComponentResult> InvokeAsync()
{
var menus = await _context.TopMenu.ToListAsync();
return View("TopMenu", menus);
}
}
}
Shared/Components/TopMenu/TopMenu.cshtml
@{
Layout = null;
}
@model IEnumerable<WebApplication.Models.TopMenu>
<ul id="nav" class="sf-menu">
<li><a href="#">MainPage</a></li>
@{
foreach (var item in Model)
{
<li>
@if (item.ParentId == null && Model.Where(a => a.ParentId == item.Id).Any())
{
<a href="/PageDetail/@[email protected]">@item.Name</a>
}
else if (item.ParentId == null && Model.Where(a => a.ParentId != item.Id).Any())
{
var link = "";
if (!String.IsNullOrEmpty(item.Link)) { link = item.Link; }
else { link = "/PageDetail" + item.Name + "-" + item.Id; }
<a href="@link">@item.Name</a>
}
<ul>
@foreach (var item1 in Model.Where(a => a.ParentId == item.Id))
{
<li><a style="text-transform:none;" href="/PageDetail/@[email protected]">@item.Name</a></li>
}
</ul>
</li>
}
}
</ul>
_Layout.cshtml
<div class="col-md-8">
<!-- Menu Partial -->
@await Component.InvokeAsync("TopMenu")
</div>
Solution 1:[1]
1_create _ViewImports.cshtml in Views folder write this line
@addTagHelper *,Microsoft.AspNetCore.Mvc.TagHelpers
2_use tagHelper in Layout.cshtml
@{
var menus = (IEnumerable<WebApplication.Models.TopMenu>)ViewBag.menus;
}
<div class="col-md-8">
<!-- Menu Partial -->
<partial name="TopMenu.cshtml" model="@menus" />
</div>
other
<partial name="~/Views/MainPage/TopMenu.cshtml" model="@menus" />
Solution 2:[2]
It might be because you forgot to add data in a html tag.
<a style="text-transform:none;" href="/PageDetail/@[email protected]" >@item.Title</a>
Solution 3:[3]
I have the same problem as your, rendering a partial view in the layout, if the partial view has a model, in this case, we can use ViewBag to pass the model . But we need to rewrite ViewBag in the corresponding action if we use the Layout page in each page.
Option 1:
In controller:
public IActionResult Index()
{
var topMenu = new List<TopMenu>()
{
new TopMenu { Name = "Khushbu",Id= 1,Link = "Link1", ParentId = 1 },
new TopMenu { Name = "Mohan", Id = 2 ,Link = "Link2", ParentId = 2},
new TopMenu { Name = "John", Id = 3 ,Link = "Link3", ParentId = 3},
new TopMenu { Name = "Martin", Id= 4,Link = "Link4", ParentId = 4},
new TopMenu { Name = "Due", Id= 5,Link = "Link5", ParentId = 5 }
}; // you also can get menus from database
ViewBag.menus = topMenu;
return View();
}
public IActionResult Privacy()
{
var topMenu = new List<TopMenu>()
{
new TopMenu { Name = "Khushbu",Id= 1,Link = "Link1", ParentId = 1 },
new TopMenu { Name = "Mohan", Id = 2 ,Link = "Link2", ParentId = 2},
new TopMenu { Name = "John", Id = 3 ,Link = "Link3", ParentId = 3},
new TopMenu { Name = "Martin", Id= 4,Link = "Link4", ParentId = 4},
new TopMenu { Name = "Due", Id= 5,Link = "Link5", ParentId = 5 }
};
ViewBag.menus = topMenu;
return View();
}
My TopMenu.cshtml is in shared folder, in layout add this :
@{
var menus = (IEnumerable<TopMenu>)ViewBag.menus;
}
<div class="col-md-8">
<!-- MenĂ¼ Partial -->
@await Html.PartialAsync("~/Views/Shared/TopMenu.cshtml",menus);
result:
So, in this case, I prefer to use ViewComponent. Read ViewComponent to know more.
Option2:
1.Create new folder named ViewComponents. In this folder, create new class named TopMenuViewComponent.cs as below:
[ViewComponent(Name = "TopMenu")]
public class TopMenuViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync()
{
List<TopMenu> menus = new List<TopMenu>() {
new TopMenu { Name = "Khushbu",Id= 1,Link = "Link1", ParentId = 1 },
new TopMenu { Name = "Mohan", Id = 2 ,Link = "Link2", ParentId = 2},
new TopMenu { Name = "John", Id = 3 ,Link = "Link3", ParentId = 3},
new TopMenu { Name = "Martin", Id= 4,Link = "Link4", ParentId = 4},
new TopMenu { Name = "Due", Id= 5,Link = "Link5", ParentId = 5 }
};// you can also get from database
return View("TopMenu", menus);
}
}
2.In Views folder, create new folders with path Views\Shared\Components\TopMenu. In TopMenu folder, add TopMenu.cshtml
3.In layout, add below code
@await Component.InvokeAsync("TopMenu")
Result:
Update
[ViewComponent(Name = "TopMenu")]
public class TopMenuViewComponent : ViewComponent
{
private readonly ViewComponentMVCContext _context;
public TopMenuViewComponent(ViewComponentMVCContext context)
{
_context = context;
}
public async Task<IViewComponentResult> InvokeAsync()
{
var menus = await _context.TopMenu.ToListAsync();
return View("TopMenu", menus);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | h.abdizadeh |
| Solution 2 | Cemil Arancak |
| Solution 3 |



