Reputation: 485
I am brand new to ASP.NET Core MVC. I'll preface this question by saying I have read the other similar questions, but they weren't exactly the same problem I am having.
I am trying to implement a dynamic left side navigation, where each of the buttons are loaded from my database.
When I call @Html.Action("NavMenu", "Nav")
in my "_Layout.cshtml" I get the error
Error CS1929
'IHtmlHelper' does not contain a definition for 'Action' and the best extension method overload 'UrlHelperExtensions.Action(IUrlHelper, string, object)' requires a receiver of type 'IUrlHelper'
One of the other similar questions led me to adding @using System.Web.Mvc.Html
to the top of my "_ViewImports" and that leads to the error:
CS7069: Reference to type 'RouteValueDictionary' Claims it is defined in 'System.Web', but it could not be found
Also the answer said @html.Action()
should be built in to Core 2.0
using @await Html.PartialAsync("_SideNav")
only works on my Index view, as that view has @model IEnumerable<HSCWebApp.Models.HSCTable>
but my other views need @model HSCWebApp.Models.HSCTable
, which causes "_SideNav" to crash
I am 100% open to other ways to implement this.
In NuGet I have installed:
EDIT:
I am also getting these warnings during build:
Warning NU1701 Package 'Microsoft.AspNet.Mvc 5.2.2' was restored using '.NETFramework,Version=v4.6.1' instead of the project target framework '.NETCoreApp,Version=v2.1'. This package may not be fully compatible with your project.
along with ones for Entity Framework, AspNet.Razor AspNet.Webpages
Would these warnings affect my references in some way?
Here are the files:
Controller: ("NavController.cs")
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using HSCWebApp.Models;
using Microsoft.EntityFrameworkCore;
namespace HSCWebApp.Controllers
{
public class NavController : Controller
{
private readonly HSCWebAppContext _context;
public NavController(HSCWebAppContext context)
{
_context = context;
}
public ActionResult NavMenu()
{
NavViewModel nav = new NavViewModel();
List<NavViewModel> navList = new List<NavViewModel>();
var items = from n in _context.HSCTable select n;
List<HSCTable> tableList = items.ToList<HSCTable>();
for (int i = 0; i < tableList.Count(); i++)
{
nav.Id = tableList[i].ID;
nav.DepartmentName = tableList[i].DepartmentName;
nav.sel = tableList[i].sel;
navList.Add(nav);
}
//var movies = from m in _context.Movie select m;
//IEnumerable<NavViewModel> en = navList;
//IEnumerable<HSCTable> en = tableList;
return PartialView("_SideNav", tableList);
}
}
}
Model: ("NavViewModel.cs")
using System.ComponentModel.DataAnnotations.Schema;
namespace HSCWebApp.Models
{
[Table("HSCTable")]
public class NavViewModel
{
public NavViewModel(){
int Id = this.Id;
string DepartmentName = this.DepartmentName;
string sel = this.sel;
}
public int Id { get; set; }
public string DepartmentName { get; set; }
public string sel { get; set; }
}
}
View: ("_SideNav.cshtml")
@model IEnumerable<HSCWebApp.Models.HSCTable>
@using System;
@using System.Collections;
@using System.Linq;
@{
List<List<string>> navButtons = new List<List<string>>();
int listIndex = 0;
int INITIAL = 0;
navButtons.Add(new List<string>());
navButtons[listIndex].Add("");
}
<body>
<div class="sidenav">
@{
foreach (var item in Model)
{
if (navButtons[listIndex][INITIAL].Equals(null)
|| navButtons[listIndex][INITIAL].Equals(""))
{
// if the list of lists is empty, add the department name
//initialize the list with with the department name
navButtons[listIndex][INITIAL] = item.DepartmentName;
//add the current select
navButtons[listIndex].Add(item.sel);
}
else if (navButtons[listIndex][INITIAL].Equals(item.DepartmentName))
{
// if the current item's department name is the same
// is the current list's department name,
// add it's selectn
navButtons[listIndex].Add(item.sel);
}
else if (!item.DepartmentName.Equals(navButtons[listIndex][INITIAL]))
{
// if the current item's department name
// is not the same as the initial of this list,
// create new list
navButtons.Add(new List<string>());
listIndex++;
navButtons[listIndex].Add(item.DepartmentName);
navButtons[listIndex].Add(item.sel);
}
}
for (int i = 0; i < navButtons.Count; i++)
{
<button class="accordion"
onclick="openAccordion(this)">
@navButtons[i][INITIAL]
</button>
<div class="tab">
@for (int j = 1; j < navButtons[i].Count; j++)
{
<a class="tabLinks NoPrint"
onclick="openTab(this)"
asp-action="Details"
asp-route-id="@navButtons[i][j]">
@navButtons[i][j].ToString()
</a>
}
</div>
}
// @Url.Action("Details", "HSCTables", new { id = 1 })
//onclick = "location.href='@Url.Action("Details","HSCTables", new { id = 1 })
}
</div>
</body>
Thank you very much for your time.
Upvotes: 3
Views: 8506
Reputation: 2867
"Posting as an answer".
Like I said, Html.Action was removed from ASP.NET Core and was replaced for ViewComponents.
There is a good tutorial in Microsoft Docs, you can see here. Explaining about the advantages, the place when you can put the View for your ViewComponent, how to use parameters and so on.
Upvotes: 2
Reputation: 485
As @Tiago Ávila said, Html.Action
was removed from Asp.NET Core, so I stopped trying to do this with @html.action
but rather with View Components, as @Llazar suggested, and it worked!
My View Component:
public class NavViewComponent : ViewComponent
{
private readonly HSCWebAppContext _context;
public NavViewComponent(HSCWebAppContext context)
{
_context = context;
}
public IViewComponentResult Invoke()
{
NavViewModel nav = new NavViewModel();
List<NavViewModel> navList = new List<NavViewModel>();
var items = from n in _context.HSCTable select n;
List<HSCTable> tableList = items.ToList<HSCTable>();
for (int i = 0; i < tableList.Count(); i++)
{
nav.Id = tableList[i].ID;
nav.DepartmentName = tableList[i].DepartmentName;
nav.sel = tableList[i].sel;
navList.Add(nav);
}
return View("_SideNav",tableList);
}
}
My call in _Layout:
@await Component.InvokeAsync("Nav")
Nothing else needed to be changed. Thanks for your help!
Upvotes: 3