I am very new to ASP.NET Core 8.0 MVC. What I've learned so far is the MVC structure always triggers a postback when changing views.
With my current application (which was built as a static page app in ASP.NET on .NET 4.8.1 with 1 SiteMaster/ChildPage [which swapped my sub pages inside it] ) I was able to load my navigation UI from SQL with pretty much 1 API request call unless the user refreshed the browser tab.
The goal of storing my navigation options in SQL (icon, text, etc) was so their text/icons could be changed in SQL without a code change.
In ASP.NET Core MVC, every view I load triggers the postback and I end up calling the SQL request to rebuild it otherwise it is lost. Is this normal practice with ASP.NET Core MVC? This seems like a major increase in API request due to the postback response. Is there any way to simulate how static pages worked in ASP.NET on .NET 4.8.1, with ASP.NET Core MVC so that the "outer wrapper/master/layout" stays static?
I've debated using a cookie for each nav icon (since at the moment I only have 6 options) but this seems excessive... I am also trying to avoid storing the nav in a Session object because I host my site in Azure (which has in the past shown poor response to keeping sessions alive correctly).
You could try using the Partial Views with AJAX which can help you to load the part of the page without a full postback.
You could try this below code:
wwwroot/js/site.js:
$(document).on('click', 'a.ajax-link', function (e) {
e.preventDefault();
var url = $(this).attr('href');
$.get(url, function (data) {
var newContent = $(data).find('#content').html();
$('#content').html(newContent);
window.history.pushState({ path: url }, '', url);
});
});
Controllers/HomeController.cs:
using Microsoft.AspNetCore.Mvc;
using MyMvcApp.Models;
using MyMvcApp.Services;
using System.Collections.Generic;
namespace MyMvcApp.Controllers
{
public class HomeController : Controller
{
private readonly NavigationService _navService;
public HomeController(NavigationService navService)
{
_navService = navService;
}
public IActionResult Index()
{
ViewData["NavigationItems"] = _navService.GetNavigationItems();
return View();
}
public IActionResult About()
{
ViewData["NavigationItems"] = _navService.GetNavigationItems();
return View();
}
public IActionResult Contact()
{
ViewData["NavigationItems"] = _navService.GetNavigationItems();
return View();
}
}
}
Views/Home/About.cshtml:
@{
Layout = "_Layout";
ViewBag.Title = "About";
}
<div id="content">
<h2>About</h2>
<p>Welcome to the About page.</p>
</div>
Views/Shared/_Navigation.cshtml:
@model IEnumerable<MyMvcApp.Models.NavigationItem>
<nav>
<ul>
@foreach (var item in Model)
{
<li>
<a class="ajax-link" href="@item.Url">
<i class="fa @item.Icon"></i>
@item.Text - Rendered from Partial View
</a>
</li>
}
</ul>
</nav>
Views/Shared/_Layout.cshtml:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - MyMvcApp</title>
<link rel="stylesheet" href="~/css/site.css" />
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="~/js/site.js"></script>
</head>
<body>
<div id="navigation">
@await Html.PartialAsync("_Navigation", ViewData["NavigationItems"] as IEnumerable<MyMvcApp.Models.NavigationItem>)
</div>
<div id="content">
@RenderBody()
</div>
</body>
</html>
Services/NavigationService.cs:
using Microsoft.Extensions.Caching.Memory;
using MyMvcApp.Models;
using System.Collections.Generic;
using System.Linq;
namespace MyMvcApp.Services
{
public class NavigationService
{
private readonly IMemoryCache _cache;
// Simulating database with a static list
private static readonly List<NavigationItem> _navigationItems = new List<NavigationItem>
{
new NavigationItem { Url = "/home", Icon = "fa-home", Text = "Home" },
new NavigationItem { Url = "/home/about", Icon = "fa-info", Text = "About" },
new NavigationItem { Url = "/home/contact", Icon = "fa-phone", Text = "Contact" }
};
public NavigationService(IMemoryCache cache)
{
_cache = cache;
}
public IEnumerable<NavigationItem> GetNavigationItems()
{
if (!_cache.TryGetValue("NavigationItems", out IEnumerable<NavigationItem> navItems))
{
navItems = _navigationItems.ToList();
_cache.Set("NavigationItems", navItems);
}
return navItems;
}
}
}
This is just sample code you can modify based on your requirement. Document link:
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/partial?view=aspnetcore-8.0