From 38baf9f749b13cd5065030d04c80d4f15a16eab0 Mon Sep 17 00:00:00 2001 From: OlgunR Date: Mon, 2 Feb 2026 09:01:08 +0100 Subject: [PATCH] Integrate DevExpress Web Dashboard into API and Blazor Added DevExpress Dashboard to ASP.NET Core API and both Blazor WASM/Server frontends. Configured dashboard storage, sample data source, and API endpoint. Updated Blazor projects with dashboard packages, styles, and a new dashboard page. Navigation and configuration updated to support dashboard integration. --- .../Controllers/DefaultDashboardController.cs | 14 ++++++++ .../Data/Dashboards/DefaultDashboard.xml | 4 +++ DbFirst.API/DbFirst.API.csproj | 5 +++ DbFirst.API/Program.cs | 35 +++++++++++++++++++ DbFirst.BlazorWasm/App.razor | 3 +- DbFirst.BlazorWasm/DbFirst.BlazorWasm.csproj | 5 ++- DbFirst.BlazorWasm/Layout/NavMenu.razor | 5 +++ DbFirst.BlazorWasm/Pages/Dashboard.razor | 12 +++++++ DbFirst.BlazorWasm/_Imports.razor | 2 ++ DbFirst.BlazorWasm/wwwroot/index.html | 10 ++++++ DbFirst.BlazorWebApp/Components/App.razor | 12 +++++++ .../Components/Layout/NavMenu.razor | 5 +++ .../Components/Pages/Dashboard.razor | 12 +++++++ .../Components/_Imports.razor | 3 ++ .../DbFirst.BlazorWebApp.csproj | 5 ++- DbFirst.BlazorWebApp/Program.cs | 3 ++ .../appsettings.Development.json | 3 +- DbFirst.BlazorWebApp/appsettings.json | 1 + 18 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 DbFirst.API/Controllers/DefaultDashboardController.cs create mode 100644 DbFirst.API/Data/Dashboards/DefaultDashboard.xml create mode 100644 DbFirst.BlazorWasm/Pages/Dashboard.razor create mode 100644 DbFirst.BlazorWebApp/Components/Pages/Dashboard.razor diff --git a/DbFirst.API/Controllers/DefaultDashboardController.cs b/DbFirst.API/Controllers/DefaultDashboardController.cs new file mode 100644 index 0000000..960a05e --- /dev/null +++ b/DbFirst.API/Controllers/DefaultDashboardController.cs @@ -0,0 +1,14 @@ +using DevExpress.DashboardAspNetCore; +using DevExpress.DashboardWeb; +using Microsoft.AspNetCore.DataProtection; + +namespace BlazorDashboardApp.Server +{ + public class DefaultDashboardController : DashboardController + { + public DefaultDashboardController(DashboardConfigurator configurator, IDataProtectionProvider? dataProtectionProvider = null) + : base(configurator, dataProtectionProvider) + { + } + } +} \ No newline at end of file diff --git a/DbFirst.API/Data/Dashboards/DefaultDashboard.xml b/DbFirst.API/Data/Dashboards/DefaultDashboard.xml new file mode 100644 index 0000000..a13c39d --- /dev/null +++ b/DbFirst.API/Data/Dashboards/DefaultDashboard.xml @@ -0,0 +1,4 @@ + + + +</Dashboard> \ No newline at end of file diff --git a/DbFirst.API/DbFirst.API.csproj b/DbFirst.API/DbFirst.API.csproj index 433fe77..4f70300 100644 --- a/DbFirst.API/DbFirst.API.csproj +++ b/DbFirst.API/DbFirst.API.csproj @@ -9,6 +9,7 @@ <ItemGroup> <PackageReference Include="AutoMapper" Version="12.0.1" /> <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" /> + <PackageReference Include="DevExpress.AspNetCore.Dashboard" Version="25.2.3" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.22" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.22" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.22"> @@ -25,4 +26,8 @@ <ProjectReference Include="..\DbFirst.Infrastructure\DbFirst.Infrastructure.csproj" /> </ItemGroup> + <ItemGroup> + <Folder Include="Data\Dashboards\" /> + </ItemGroup> + </Project> diff --git a/DbFirst.API/Program.cs b/DbFirst.API/Program.cs index 2fb8a22..6996abe 100644 --- a/DbFirst.API/Program.cs +++ b/DbFirst.API/Program.cs @@ -4,6 +4,11 @@ using DbFirst.Application.Repositories; using DbFirst.Domain; using DbFirst.Infrastructure; using DbFirst.Infrastructure.Repositories; +using DevExpress.AspNetCore; +using DevExpress.DashboardAspNetCore; +using DevExpress.DashboardCommon; +using DevExpress.DashboardWeb; +using DevExpress.DataAccess.Json; var builder = WebApplication.CreateBuilder(args); @@ -44,6 +49,33 @@ builder.Services.AddApplication(); builder.Services.AddScoped<ICatalogRepository, CatalogRepository>(); +builder.Services.AddDevExpressControls(); +builder.Services.AddScoped<DashboardConfigurator>((IServiceProvider serviceProvider) => { + var dashboardsPath = Path.Combine(builder.Environment.ContentRootPath, "Data", "Dashboards"); + Directory.CreateDirectory(dashboardsPath); + + var defaultDashboardPath = Path.Combine(dashboardsPath, "DefaultDashboard.xml"); + if (!File.Exists(defaultDashboardPath)) + { + var defaultDashboard = new Dashboard(); + defaultDashboard.Title.Text = "Default Dashboard"; + defaultDashboard.SaveToXml(defaultDashboardPath); + } + + DashboardConfigurator configurator = new DashboardConfigurator(); + // Register Dashboard Storage + configurator.SetDashboardStorage(new DashboardFileStorage(dashboardsPath)); + // Create a sample JSON data source + DataSourceInMemoryStorage dataSourceStorage = new DataSourceInMemoryStorage(); + DashboardJsonDataSource jsonDataSourceUrl = new DashboardJsonDataSource("JSON Data Source (URL)"); + jsonDataSourceUrl.JsonSource = new UriJsonSource( + new Uri("https://raw.githubusercontent.com/DevExpress-Examples/DataSources/master/JSON/customers.json")); + jsonDataSourceUrl.RootElement = "Customers"; + dataSourceStorage.RegisterDataSource("jsonDataSourceUrl", jsonDataSourceUrl.SaveToXml()); + configurator.SetDataSourceStorage(dataSourceStorage); + return configurator; +}); + var app = builder.Build(); // Configure the HTTP request pipeline. @@ -55,10 +87,13 @@ if (app.Environment.IsDevelopment()) app.UseMiddleware<ExceptionHandlingMiddleware>(); +app.UseDevExpressControls(); app.UseHttpsRedirection(); app.UseCors(); app.UseAuthorization(); +app.MapDashboardRoute("api/dashboard", "DefaultDashboard"); + app.MapControllers(); app.Run(); diff --git a/DbFirst.BlazorWasm/App.razor b/DbFirst.BlazorWasm/App.razor index 6f372a0..3d316ad 100644 --- a/DbFirst.BlazorWasm/App.razor +++ b/DbFirst.BlazorWasm/App.razor @@ -4,7 +4,8 @@ • Der Router-Komponent in App.razor entscheidet, welche Blazor-Komponente basierend auf der URL geladen wird. kurz: Steuert die Navigation und das Rendering der Blazor-Komponenten. *@ - +@DxResourceManager.RegisterTheme(Themes.Fluent) +@DxResourceManager.RegisterScripts() <Router AppAssembly="@typeof(App).Assembly"> <Found Context="routeData"> <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> diff --git a/DbFirst.BlazorWasm/DbFirst.BlazorWasm.csproj b/DbFirst.BlazorWasm/DbFirst.BlazorWasm.csproj index 67b3338..cdcb88f 100644 --- a/DbFirst.BlazorWasm/DbFirst.BlazorWasm.csproj +++ b/DbFirst.BlazorWasm/DbFirst.BlazorWasm.csproj @@ -7,9 +7,12 @@ </PropertyGroup> <ItemGroup> + <PackageReference Include="DevExpress.Blazor" Version="25.2.3" /> + <PackageReference Include="DevExpress.Blazor.Dashboard" Version="25.2.3" /> + <PackageReference Include="DevExpress.Blazor.Themes" Version="25.2.3" /> + <PackageReference Include="DevExpress.Blazor.Themes.Fluent" Version="25.2.3" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.22" /> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.22" PrivateAssets="all" /> - <PackageReference Include="DevExpress.Blazor" Version="24.1.*" /> </ItemGroup> <ItemGroup> diff --git a/DbFirst.BlazorWasm/Layout/NavMenu.razor b/DbFirst.BlazorWasm/Layout/NavMenu.razor index c170642..8c006ab 100644 --- a/DbFirst.BlazorWasm/Layout/NavMenu.razor +++ b/DbFirst.BlazorWasm/Layout/NavMenu.razor @@ -21,6 +21,11 @@ <span class="bi bi-collection-nav-menu" aria-hidden="true"></span> Catalogs </NavLink> </div> + <div class="nav-item px-3"> + <NavLink class="nav-link" href="dashboard"> + <span class="oi oi-list-rich" aria-hidden="true"></span> Web Dashboard + </NavLink> + </div> </nav> </div> diff --git a/DbFirst.BlazorWasm/Pages/Dashboard.razor b/DbFirst.BlazorWasm/Pages/Dashboard.razor new file mode 100644 index 0000000..0b228d0 --- /dev/null +++ b/DbFirst.BlazorWasm/Pages/Dashboard.razor @@ -0,0 +1,12 @@ +@page "/dashboard" +@inject Microsoft.Extensions.Configuration.IConfiguration Configuration + +<DxDashboard Endpoint="@DashboardEndpoint" style="width: 100%; height: 800px;"> +</DxDashboard> + +@code { + private string DashboardEndpoint => $"{Configuration["ApiBaseUrl"]?.TrimEnd('/')}/api/dashboard"; +} + +@* <DxDashboard Endpoint="api/dashboard" WorkingMode="WorkingMode.ViewerOnly" style="width: 100%; height: 800px;"> +</DxDashboard> *@ \ No newline at end of file diff --git a/DbFirst.BlazorWasm/_Imports.razor b/DbFirst.BlazorWasm/_Imports.razor index fb7bcf1..27c188c 100644 --- a/DbFirst.BlazorWasm/_Imports.razor +++ b/DbFirst.BlazorWasm/_Imports.razor @@ -11,3 +11,5 @@ @using DbFirst.BlazorWasm.Models @using DbFirst.BlazorWasm.Services @using DevExpress.Blazor +@using DevExpress.DashboardBlazor +@using DevExpress.DashboardWeb \ No newline at end of file diff --git a/DbFirst.BlazorWasm/wwwroot/index.html b/DbFirst.BlazorWasm/wwwroot/index.html index f146c9f..840769e 100644 --- a/DbFirst.BlazorWasm/wwwroot/index.html +++ b/DbFirst.BlazorWasm/wwwroot/index.html @@ -17,6 +17,16 @@ <base href="/" /> <!-- Stylesheets für DevExpress und Bootstrap --> + + <link href="_content/DevExpress.Blazor.Dashboard/ace.css" rel="stylesheet" /> + <link href="_content/DevExpress.Blazor.Dashboard/ace-theme-dreamweaver.css" rel="stylesheet" /> + <link href="_content/DevExpress.Blazor.Dashboard/ace-theme-ambiance.css" rel="stylesheet" /> + <link href="_content/DevExpress.Blazor.Dashboard/dx.light.css" rel="stylesheet" /> + <link href="_content/DevExpress.Blazor.Dashboard/dx-analytics.common.css" rel="stylesheet" /> + <link href="_content/DevExpress.Blazor.Dashboard/dx-analytics.light.css" rel="stylesheet" /> + <link href="_content/DevExpress.Blazor.Dashboard/dx-querybuilder.css" rel="stylesheet" /> + <link href="_content/DevExpress.Blazor.Dashboard/dx-dashboard.light.min.css" rel="stylesheet" /> + <link rel="stylesheet" href="_content/DevExpress.Blazor.Themes/bootstrap-external.bs5.min.css" /> <link rel="stylesheet" href="_content/DevExpress.Blazor.Themes/icons.css" /> <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" /> diff --git a/DbFirst.BlazorWebApp/Components/App.razor b/DbFirst.BlazorWebApp/Components/App.razor index 93223a9..5972a1e 100644 --- a/DbFirst.BlazorWebApp/Components/App.razor +++ b/DbFirst.BlazorWebApp/Components/App.razor @@ -5,6 +5,18 @@ <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <base href="/" /> + @DxResourceManager.RegisterTheme(Themes.Fluent) + @DxResourceManager.RegisterScripts() + + <link href="_content/DevExpress.Blazor.Dashboard/ace.css" rel="stylesheet" /> + <link href="_content/DevExpress.Blazor.Dashboard/ace-theme-dreamweaver.css" rel="stylesheet" /> + <link href="_content/DevExpress.Blazor.Dashboard/ace-theme-ambiance.css" rel="stylesheet" /> + <link href="_content/DevExpress.Blazor.Dashboard/dx.light.css" rel="stylesheet" /> + <link href="_content/DevExpress.Blazor.Dashboard/dx-analytics.common.css" rel="stylesheet" /> + <link href="_content/DevExpress.Blazor.Dashboard/dx-analytics.light.css" rel="stylesheet" /> + <link href="_content/DevExpress.Blazor.Dashboard/dx-querybuilder.css" rel="stylesheet" /> + <link href="_content/DevExpress.Blazor.Dashboard/dx-dashboard.light.min.css" rel="stylesheet" /> + <link rel="stylesheet" href="bootstrap/bootstrap.min.css" /> <link rel="stylesheet" href="app.css" /> <link rel="stylesheet" href="DbFirst.BlazorWebApp.styles.css" /> diff --git a/DbFirst.BlazorWebApp/Components/Layout/NavMenu.razor b/DbFirst.BlazorWebApp/Components/Layout/NavMenu.razor index 1a81832..4363fd0 100644 --- a/DbFirst.BlazorWebApp/Components/Layout/NavMenu.razor +++ b/DbFirst.BlazorWebApp/Components/Layout/NavMenu.razor @@ -25,6 +25,11 @@ <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Weather </NavLink> </div> + <div class="nav-item px-3"> + <NavLink class="nav-link" href="dashboard"> + <span class="oi oi-list-rich" aria-hidden="true"></span> Web Dashboard + </NavLink> + </div> </nav> </div> diff --git a/DbFirst.BlazorWebApp/Components/Pages/Dashboard.razor b/DbFirst.BlazorWebApp/Components/Pages/Dashboard.razor new file mode 100644 index 0000000..0b228d0 --- /dev/null +++ b/DbFirst.BlazorWebApp/Components/Pages/Dashboard.razor @@ -0,0 +1,12 @@ +@page "/dashboard" +@inject Microsoft.Extensions.Configuration.IConfiguration Configuration + +<DxDashboard Endpoint="@DashboardEndpoint" style="width: 100%; height: 800px;"> +</DxDashboard> + +@code { + private string DashboardEndpoint => $"{Configuration["ApiBaseUrl"]?.TrimEnd('/')}/api/dashboard"; +} + +@* <DxDashboard Endpoint="api/dashboard" WorkingMode="WorkingMode.ViewerOnly" style="width: 100%; height: 800px;"> +</DxDashboard> *@ \ No newline at end of file diff --git a/DbFirst.BlazorWebApp/Components/_Imports.razor b/DbFirst.BlazorWebApp/Components/_Imports.razor index 0e069fa..2fc8dc7 100644 --- a/DbFirst.BlazorWebApp/Components/_Imports.razor +++ b/DbFirst.BlazorWebApp/Components/_Imports.razor @@ -8,3 +8,6 @@ @using Microsoft.JSInterop @using DbFirst.BlazorWebApp @using DbFirst.BlazorWebApp.Components +@using DevExpress.Blazor +@using DevExpress.DashboardBlazor +@using DevExpress.DashboardWeb \ No newline at end of file diff --git a/DbFirst.BlazorWebApp/DbFirst.BlazorWebApp.csproj b/DbFirst.BlazorWebApp/DbFirst.BlazorWebApp.csproj index 7756477..f2de668 100644 --- a/DbFirst.BlazorWebApp/DbFirst.BlazorWebApp.csproj +++ b/DbFirst.BlazorWebApp/DbFirst.BlazorWebApp.csproj @@ -7,7 +7,10 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="DevExpress.Blazor" Version="25.1.3" /> + <PackageReference Include="DevExpress.Blazor" Version="25.2.3" /> + <PackageReference Include="DevExpress.Blazor.Dashboard" Version="25.2.3" /> + <PackageReference Include="DevExpress.Blazor.Themes" Version="25.2.3" /> + <PackageReference Include="DevExpress.Blazor.Themes.Fluent" Version="25.2.3" /> </ItemGroup> </Project> diff --git a/DbFirst.BlazorWebApp/Program.cs b/DbFirst.BlazorWebApp/Program.cs index 9a6fe6b..d244f42 100644 --- a/DbFirst.BlazorWebApp/Program.cs +++ b/DbFirst.BlazorWebApp/Program.cs @@ -1,4 +1,5 @@ using DbFirst.BlazorWebApp.Components; +using DevExpress.Blazor; var builder = WebApplication.CreateBuilder(args); @@ -6,6 +7,8 @@ var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorComponents() .AddInteractiveServerComponents(); +builder.Services.AddDevExpressBlazor(); + var app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/DbFirst.BlazorWebApp/appsettings.Development.json b/DbFirst.BlazorWebApp/appsettings.Development.json index 0c208ae..702a28b 100644 --- a/DbFirst.BlazorWebApp/appsettings.Development.json +++ b/DbFirst.BlazorWebApp/appsettings.Development.json @@ -4,5 +4,6 @@ "Default": "Information", "Microsoft.AspNetCore": "Warning" } - } + }, + "ApiBaseUrl": "https://localhost:7204/" } diff --git a/DbFirst.BlazorWebApp/appsettings.json b/DbFirst.BlazorWebApp/appsettings.json index 10f68b8..73c9700 100644 --- a/DbFirst.BlazorWebApp/appsettings.json +++ b/DbFirst.BlazorWebApp/appsettings.json @@ -5,5 +5,6 @@ "Microsoft.AspNetCore": "Warning" } }, + "ApiBaseUrl": "https://localhost:7204/", "AllowedHosts": "*" }