DS.Foundation.WebApp
8.4.0
dotnet add package DS.Foundation.WebApp --version 8.4.0
NuGet\Install-Package DS.Foundation.WebApp -Version 8.4.0
<PackageReference Include="DS.Foundation.WebApp" Version="8.4.0" />
<PackageVersion Include="DS.Foundation.WebApp" Version="8.4.0" />
<PackageReference Include="DS.Foundation.WebApp" />
paket add DS.Foundation.WebApp --version 8.4.0
#r "nuget: DS.Foundation.WebApp, 8.4.0"
#:package DS.Foundation.WebApp@8.4.0
#addin nuget:?package=DS.Foundation.WebApp&version=8.4.0
#tool nuget:?package=DS.Foundation.WebApp&version=8.4.0
DS.Foundation.WebApp
Menú principal para aplicaciones ASP.NET Core MVC/Razor:
Combina los ítems de uno o más orígenes de datos.
Los filtra según los roles del usuario: los roles generales y, si se configura, los roles que tiene en la aplicación actual.
Arma el árbol de menú.
Lo dibuja con el tag helper
<ds-main-menu>, con marcado de Bootstrap 5.Target framework:
net8.0(Razor class library).Dependencias:
DS.Foundation.Authentication8.4.0 (y por ellaDS.Foundation) y el framework compartido de ASP.NET Core.
Instalación
<PackageReference Include="DS.Foundation.WebApp" Version="8.4.0" />
Registro
using DS.Foundation.WebApp.MainMenu;
builder.Services.AddControllersWithViews();
builder.Services
.AddWebAppMainMenu(options => options.ApplicationCode = "CRM") // IMainMenuProvider (scoped), IHttpContextAccessor y MainMenuOptions
.AddMenuDataSource<MenuPrincipal>(); // IMenuDataSource (scoped); puede agregar varios
AddWebAppMainMenu() sin parámetros sigue disponible y filtra solo por roles generales.
En Views/_ViewImports.cshtml:
@addTagHelper *, DS.Foundation.WebApp
Configuración
MainMenuOptions
| Propiedad | Tipo | Valor por defecto | Obligatoria |
|---|---|---|---|
ApplicationCode |
string |
"" |
No. Si tiene valor, los roles del usuario en esa aplicación (claim ApplicationRoles) se suman a los roles generales. Se compara sin distinguir mayúsculas |
Ítems del menú (Menu)
Cada ítem se define en código:
| Propiedad | Tipo | Valor por defecto | Uso |
|---|---|---|---|
ID |
string |
"" |
Identificador único; si dos orígenes repiten un ID, gana el primero |
ParentID |
string |
null |
null = ítem raíz |
Content |
string |
"" |
Texto visible |
Url |
string |
"" |
Destino; vacío = # |
Order |
long |
0 |
Orden entre hermanos |
AllowedRoles |
List<string> |
vacía | Vacía = visible para todos; si no, el usuario necesita alguno de esos roles (sin distinguir mayúsculas) |
SelectedClass, OnClick |
string |
"" |
Se copian al modelo pero la vista incluida no los dibuja |
Roles que se usan para filtrar
- Roles generales:
UserHelper.Roles, es decir un rol por claimClaimTypes.Role. También acepta el formato anterior aDS.Foundation.Authentication8.4.0, con varios roles separados por|en un solo claim. - Roles de aplicación: si
ApplicationCodetiene valor, los roles de la entrada deApplicationRolescon ese código (UserHelper.GetApplicationRoles).
AllowedRoles se compara contra la unión de ambos.
Uso
using DS.Foundation.WebApp.MainMenu.Models;
using DS.Foundation.WebApp.MainMenu.Services;
public class MenuPrincipal : MenuDataSourceBase
{
protected override IList<Menu> BuildMenuItems(string route) => new List<Menu>
{
new Menu { ID = "ventas", Content = "Ventas", Order = 1 },
new Menu { ID = "pedidos", ParentID = "ventas", Content = "Pedidos", Url = "/pedidos", Order = 1,
SelectedClass = SelectedClass(route, "/pedidos"),
AllowedRoles = new List<string> { "SELLER" } }, // rol en la aplicación CRM
new Menu { ID = "admin", Content = "Administración", Url = "/admin", Order = 2,
AllowedRoles = new List<string> { "admin" } }, // rol general
};
}
En el layout, dentro de un <ul class="navbar-nav">:
<ds-main-menu></ds-main-menu>
Para un origen asincrónico (base de datos, API), implemente IMenuDataSource directamente; recibe los roles ya combinados en userRoles.
Errores frecuentes
| Síntoma | Causa | Solución |
|---|---|---|
InvalidOperationException: No IMenuDataSource registered… |
No se agregó ningún origen | Llamar a .AddMenuDataSource<T>() |
| No aparecen los ítems de un rol de aplicación | Falta ApplicationCode, no coincide con el código del token, o el token fue emitido con una versión anterior a 8.4.0 de DS.Foundation.Authentication |
Configurar AddWebAppMainMenu(o => o.ApplicationCode = "…") y emitir el token con 8.4.0 o posterior |
JsonException al dibujar el menú |
El claim ApplicationRoles no es JSON válido |
Emitir el token con JsonWebTokenService |
La etiqueta <ds-main-menu> aparece tal cual en el HTML |
Falta @addTagHelper *, DS.Foundation.WebApp |
Agregarlo en _ViewImports.cshtml |
| Los submenús no se despliegan | La vista usa clases y atributos de Bootstrap 5 (dropdown, data-bs-toggle) |
Incluir Bootstrap 5 y su JavaScript |
Qué no hacer
- No usar el menú como control de acceso: oculta ítems, pero las rutas deben protegerse con
[Authorize]. - No depender de
SelectedClassni deOnClicken la vista incluida: hoy no se dibujan.
Cambios
Ver CHANGELOG.md.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- DS.Foundation.Authentication (>= 8.4.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.