Migrate BI Dashboard from ASP.NET MVC to ASP.NET Core MVC
- 6 minutes to read
You can migrate ASP.NET MVC Dashboard Extension customizations to a new .NET application. The Dashboard Control API is the same regardless of the target platform, so you can migrate customization code to a new app with minimal adjustments. A custom implementation of ASP.NET MVC Dashboard services can also be used in a new application because interface implementation is similar in all web frameworks.
Prerequisites
- .NET 8.0 or later SDK
- Visual Studio 2022 v17.0+
You may require additional packages to run our Dashboard components on Linux or iOS: Linux and MacOS Specifics.
Create an ASP.NET Core Application
In Visual Studio, create a new project as follows:
- On the start page, select ASP.NET Core Web App as the project template.
- In the Configure your new project dialog, enter
WebDashboardAspNetCore
for Project name. - In the Additional information dialog, specify the target framework (.NET 8.0).
Manage Packages and Libraries
Install NuGet Packages
In the project, open the NuGet Package Manager and set the package source to All. Install the following packages:
- DevExpress.AspNetCore.Dashboard
- BuildBundlerMinifier
Refer to the following topic to install and manage libraries using DevExpress NuGet feed: Setup Visual Studio’s NuGet Package Manager.
Install npm Packages
Note
Make sure you have Node.js and npm installed on your machine.
Open the Add New Item dialog (Ctrl+Shift+A
), create the npm Configuration File (package.json), and add the following npm packages:
{
...
"devDependencies": {
"devextreme-dist": "25.1-stable",
"@devexpress/analytics-core": "25.1-stable",
"devexpress-dashboard": "25.1-stable"
}
}
Save package.json, right-click it and select Restore Packages.
Bundle Resources (bundleconfig.json)
Create the bundleconfig.json file in the root directory and add the following configuration:
[
{
"outputFileName": "wwwroot/css/site.min.css",
"inputFiles": [
"node_modules/devextreme-dist/css/dx.light.css",
"node_modules/@devexpress/analytics-core/dist/css/dx-analytics.common.css",
"node_modules/@devexpress/analytics-core/dist/css/dx-analytics.light.css",
"node_modules/@devexpress/analytics-core/dist/css/dx-querybuilder.css",
"node_modules/devexpress-dashboard/dist/css/dx-dashboard.light.min.css"
],
"minify": {
"enabled": false,
"adjustRelativePaths": false
}
},
{
"outputFileName": "wwwroot/css/ace/ace.bundle.css",
"inputFiles": [
"node_modules/ace-builds/css/ace.css",
"node_modules/ace-builds/css/theme/dreamweaver.css",
"node_modules/ace-builds/css/theme/ambiance.css"
],
"minify": {
"enabled": false,
"adjustRelativePaths": false
}
},
{
"outputFileName": "wwwroot/js/site.min.js",
"inputFiles": [
"node_modules/jquery/dist/jquery.min.js",
"node_modules/knockout/build/output/knockout-latest.js",
"node_modules/ace-builds/src-min-noconflict/ace.js",
"node_modules/ace-builds/src-min-noconflict/ext-language_tools.js",
"node_modules/ace-builds/src-min-noconflict/theme-dreamweaver.js",
"node_modules/ace-builds/src-min-noconflict/theme-ambiance.js",
"node_modules/devextreme-dist/js/dx.all.js",
"node_modules/@devexpress/analytics-core/dist/js/dx-analytics-core.min.js",
"node_modules/@devexpress/analytics-core/dist/js/dx-querybuilder.min.js",
"node_modules/devexpress-dashboard/dist/js/dx-dashboard.min.js"
],
"minify": {
"enabled": false
},
"sourceMap": false
}
]
Create the libman.json file in the root directory of the project and add the following LibMan configuration to copy icon fonts to the application’s static content folder:
{
"version": "1.0",
"defaultProvider": "filesystem",
"libraries": [
{
"library": "node_modules/ace-builds/css/",
"destination": "wwwroot/css/ace",
"files": [ "*.png", "*.svg" ]
},
{
"library": "node_modules/devextreme-dist/css/icons/",
"destination": "wwwroot/css/icons/",
"files": [
"dxicons.ttf",
"dxicons.woff",
"dxicons.woff2"
]
}
]
}
Configure LibMan (libman.json)
Save package.json, right-click it and select Restore Packages.
Create the bundleconfig.json file in the root directory and add the following configuration:
[
{
"outputFileName": "wwwroot/css/site.min.css",
"inputFiles": [
"node_modules/devextreme-dist/css/dx.light.css",
"node_modules/@devexpress/analytics-core/dist/css/dx-analytics.common.css",
"node_modules/@devexpress/analytics-core/dist/css/dx-analytics.light.css",
"node_modules/@devexpress/analytics-core/dist/css/dx-querybuilder.css",
"node_modules/devexpress-dashboard/dist/css/dx-dashboard.light.min.css"
],
"minify": {
"enabled": false,
"adjustRelativePaths": false
}
},
{
"outputFileName": "wwwroot/css/ace/ace.bundle.css",
"inputFiles": [
"node_modules/ace-builds/css/ace.css",
"node_modules/ace-builds/css/theme/dreamweaver.css",
"node_modules/ace-builds/css/theme/ambiance.css"
],
"minify": {
"enabled": false,
"adjustRelativePaths": false
}
},
{
"outputFileName": "wwwroot/js/site.min.js",
"inputFiles": [
"node_modules/jquery/dist/jquery.min.js",
"node_modules/knockout/build/output/knockout-latest.js",
"node_modules/ace-builds/src-min-noconflict/ace.js",
"node_modules/ace-builds/src-min-noconflict/ext-language_tools.js",
"node_modules/ace-builds/src-min-noconflict/theme-dreamweaver.js",
"node_modules/ace-builds/src-min-noconflict/theme-ambiance.js",
"node_modules/devextreme-dist/js/dx.all.js",
"node_modules/@devexpress/analytics-core/dist/js/dx-analytics-core.min.js",
"node_modules/@devexpress/analytics-core/dist/js/dx-querybuilder.min.js",
"node_modules/devexpress-dashboard/dist/js/dx-dashboard.min.js"
],
"minify": {
"enabled": false
},
"sourceMap": false
}
]
Create the libman.json file in the root directory of the project and add the following LibMan configuration to copy icon fonts to the application’s static content folder:
{
"version": "1.0",
"defaultProvider": "filesystem",
"libraries": [
{
"library": "node_modules/ace-builds/css/",
"destination": "wwwroot/css/ace",
"files": [ "*.png", "*.svg" ]
},
{
"library": "node_modules/devextreme-dist/css/icons/",
"destination": "wwwroot/css/icons/",
"files": [
"dxicons.ttf",
"dxicons.woff",
"dxicons.woff2"
]
}
]
}
Migrate a Dashboard
The CS/VB and XML dashboards are cross-platform and can be reused in any platform dashboard application.
Configure Services on Startup (Program.cs)
All Web Dashboard services registered with DashboardConfigurator
in an ASP.NET MVC app can be registered in ASP.NET Core’s built-in DI container. You do not need to change the service definitions from your legacy app - just copy them over. Dependency injection works for all migrated services.
The following code snippet registers the DashboardFileStorage
service:
- ASP.NET MVC
protected void Application_Start(object sender, EventArgs e) { DashboardConfigurator.Default.SetDashboardStorage(new DashboardFileStorage("~/App_Data/Dashboards")); // ... }
- ASP.NET Core
var builder = WebApplication.CreateBuilder(args); builder.Services.AddScoped<DashboardConfigurator>((IServiceProvider serviceProvider) => { DashboardConfigurator configurator = new DashboardConfigurator(); configurator.SetDashboardStorage(new DashboardFileStorage(fileProvider.GetFileInfo("Data/Dashboards").PhysicalPath)); return configurator; }); var app = builder.Build();
The following code snippet references services required by DevExpress BI Dashboard:
using DevExpress.AspNetCore;
using DevExpress.DashboardAspNetCore;
using DevExpress.DashboardWeb;
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
IFileProvider? fileProvider = builder.Environment.ContentRootFileProvider;
IConfiguration? configuration = builder.Configuration;
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddDevExpressControls();
builder.Services.AddScoped<DashboardConfigurator>((IServiceProvider serviceProvider) => {
DashboardConfigurator configurator = new DashboardConfigurator();
configurator.SetDashboardStorage(new DashboardFileStorage(fileProvider.GetFileInfo("Data/Dashboards").PhysicalPath));
configurator.SetConnectionStringsProvider(new DashboardConnectionStringsProvider(configuration));
return configurator;
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseDevExpressControls();
app.MapDashboardRoute("api/dashboard", "DefaultDashboard");
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Migrate Controller Logic
Both ASP.NET MVC and ASP.NET Core apps use the DashboardController class descendant. You can migrate it as is.
- DefaultDashboardController example:
using DevExpress.DashboardAspNetCore; using DevExpress.DashboardWeb; using Microsoft.AspNetCore.DataProtection; namespace WebDashboardAspNetCore.Controllers { public class DefaultDashboardController : DashboardController { public DefaultDashboardController(DashboardConfigurator configurator, IDataProtectionProvider? dataProtectionProvider = null) : base(configurator, dataProtectionProvider) { } } }
Adjust Views
ASP.NET Core uses the DashboardBuilder options to configure the control in a view.
The following code sample displays the Dashboard control and loads a dashboard. The ControllerName
property value is the name of the controller you created earlier (without the Controller postfix):
- ASP.NET MVC View
@Html.DevExpress().Dashboard(settings => { settings.Name = "dashboardControl1"; settings.ControllerName = "DefaultDashboard"; settings.Width = Unit.Percentage(100); settings.Height = Unit.Percentage(100); settings.ClientSideEvents.BeforeRender = "onBeforeRender"; }).GetHtml()
- ASP.NET Core View
@(Html.DevExpress().Dashboard("dashboardControl1") .ControllerName("DefaultDashboard") .Width("100%") .Height("100%") .OnBeforeRender("onBeforeRender") )
Migrate Client-Side Customization
Note
This tutorial is designed for applications that use the unified DashboardControl
API, which simplifies sharing JavaScript code across platforms. Since the code is nearly identical on all supported platforms, we recommend updating your app to use this API before migrating to .NET. For details, see: Migrate from ASPxClientDashboard to DashboardControl API.
The ASP.NET Core Web Dashboard uses the same client API (DashboardControl) as ASP.NET MVC, with one key difference: in ASP.NET Core, the sender is the DashboardControl
itself. In ASP.NET MVC, you need to call GetDashboardControl()
first - the rest of the JavaScript code stays the same.
These code snippets handles the BeforeRender()
method:
Review the following documentation for more information on how to use client-side API in ASP.NET Core application: Client-Side API Overview for ASP.NET Core Dashboard.
The following code snippet registers DashboardPanelExtension
:
- ASP.NET MVC View
<script type="text/javascript"> function onBeforeRender(sender) { var dashboardControl = sender.GetDashboardControl(); dashboardControl.registerExtension(new DevExpress.Dashboard.DashboardPanelExtension(dashboardControl)); } </script> @Html.DevExpress().Dashboard(settings => { // ... settings.Name = "dashboardControl1"; settings.ClientSideEvents.BeforeRender = "onBeforeRender"; }).GetHtml()
- ASP.NET Core View
<script type="text/javascript"> function onBeforeRender(sender) { var dashboardControl = sender; dashboardControl.registerExtension(new DevExpress.Dashboard.DashboardPanelExtension(dashboardControl)); } </script> @(Html.DevExpress().Dashboard("dashboardControl1") // ... .OnBeforeRender("onBeforeRender") )
The following functionality is specific to the ASP.NET Core platform:
The Init event no longer exists in ASP.NET Core. You can rewrite your customization logic using the
BeforeRender
event.ASP.NET Core uses callbacks that have only one handler. You cannot use a subscription with the
AddHandler
method.