40 KiB
Migration Plan: Blazorise to MudBlazor in ABP Framework
Executive Summary
This document outlines a phased approach to replace Blazorise with MudBlazor as the UI component library in ABP Framework. The migration will be gradual, allowing users time to migrate their existing applications before Blazorise packages are deprecated and eventually removed.
Key Strategy: No abstraction layer - MudBlazor packages will directly replace Blazorise packages over time.
Current Architecture Analysis
Existing Blazorise Integration
The ABP Framework currently uses Blazorise (v1.8.8) with the following structure:
Core Packages:
Volo.Abp.BlazoriseUI- Core UI module with service implementationsVolo.Abp.AspNetCore.Components.Web.Theming- Theming infrastructure (currently depends on BlazoriseUI - this needs to change)
Hosting-Specific Packages:
Volo.Abp.AspNetCore.Components.Server.ThemingVolo.Abp.AspNetCore.Components.WebAssembly.ThemingVolo.Abp.AspNetCore.Components.MauiBlazor.Theming
Feature Module Packages (using Blazorise components):
Volo.Abp.Identity.BlazorVolo.Abp.TenantManagement.BlazorVolo.Abp.PermissionManagement.BlazorVolo.Abp.FeatureManagement.BlazorVolo.Abp.SettingManagement.BlazorVolo.Abp.Account.Blazor
Existing Service Abstractions
ABP already has UI-agnostic service interfaces in Volo.Abp.AspNetCore.Components:
IUiMessageService- Message dialogs (Info, Success, Warn, Error, Confirm)IUiNotificationService- Toast notificationsIUiPageProgressService- Page progress indicators
These interfaces will be reused - only the implementations change from Blazorise to MudBlazor.
Current Problem: Theming Package Dependency
The Volo.Abp.AspNetCore.Components.Web.Theming package currently depends on Volo.Abp.BlazoriseUI, but analysis shows this dependency is not necessary. The theming package uses:
BreadcrumbItemclass - A simple POCO that should be UI-agnosticPageHeader.razor- Uses Blazorise components directly (should be moved)PageToolbarExtensions.AddButton- Uses BlazoriseToolbarButton(should be moved)
Solution: Refactor theming into UI-agnostic base + UI-specific implementations.
Migration Timeline Overview
| Phase | Description | Blazorise Status |
|---|---|---|
| Phase 0 | Refactor theming architecture | Fully supported |
| Phase 1 | Create MudBlazor core packages | Fully supported |
| Phase 2 | Create MudBlazor theming | Fully supported |
| Phase 3 | Create MudBlazor CRUD components | Fully supported |
| Phase 4 | Create MudBlazor feature modules | Fully supported |
| Phase 5 | Create MudBlazor themes | Fully supported |
| Phase 6 | Update templates (MudBlazor default) | Deprecated |
| Phase 7 | Documentation & migration guides | Deprecated |
| Phase 8 | Remove Blazorise packages | Removed |
Phase 0: Refactor Theming Architecture (Pre-requisite)
Objective: Make Volo.Abp.AspNetCore.Components.Web.Theming UI-agnostic by removing its dependency on Volo.Abp.BlazoriseUI.
0.1 Move UI-Agnostic Classes
Move BreadcrumbItem from Volo.Abp.BlazoriseUI to Volo.Abp.AspNetCore.Components.Web:
framework/src/Volo.Abp.AspNetCore.Components.Web/
└── Volo/Abp/AspNetCore/Components/Web/
└── Theming/
└── BreadcrumbItem.cs # Moved from BlazoriseUI
BreadcrumbItem.cs (UI-agnostic):
namespace Volo.Abp.AspNetCore.Components.Web.Theming;
public class BreadcrumbItem
{
public string Text { get; set; }
public object? Icon { get; set; }
public string? Url { get; set; }
public BreadcrumbItem(string text, string? url = null, object? icon = null)
{
Text = text;
Url = url;
Icon = icon;
}
}
0.2 Refactor Theming Package Structure
Split the theming infrastructure:
BEFORE (Current):
─────────────────
Volo.Abp.AspNetCore.Components.Web.Theming
├── Depends on: Volo.Abp.BlazoriseUI ❌ (Problem!)
├── PageHeader.razor (Blazorise components)
├── PageToolbarExtensions.cs (uses ToolbarButton)
└── Theming infrastructure (UI-agnostic)
AFTER (Refactored):
───────────────────
Volo.Abp.AspNetCore.Components.Web.Theming (UI-Agnostic)
├── Depends on: Volo.Abp.AspNetCore.Components.Web ✓
├── Depends on: Volo.Abp.UI.Navigation ✓
├── NO dependency on BlazoriseUI or MudBlazorUI ✓
├── Theming/
│ ├── ITheme.cs
│ ├── IThemeManager.cs
│ ├── IThemeSelector.cs
│ ├── ThemeDictionary.cs
│ └── ...
├── PageToolbars/
│ ├── IPageToolbarManager.cs
│ ├── PageToolbar.cs
│ ├── PageToolbarItem.cs
│ └── ... (no UI-specific extensions)
├── Toolbars/
│ ├── IToolbarManager.cs
│ ├── Toolbar.cs
│ └── ...
├── Routing/
│ └── AbpRouterOptions.cs
└── Layout/
├── PageLayout.cs (uses BreadcrumbItem from Components.Web)
└── StandardLayouts.cs
Volo.Abp.AspNetCore.Components.Web.Theming.Blazorise (Blazorise-Specific)
├── Depends on: Volo.Abp.AspNetCore.Components.Web.Theming ✓
├── Depends on: Volo.Abp.BlazoriseUI ✓
├── AbpAspNetCoreComponentsWebThemingBlazoriseModule.cs
├── Components/
│ └── PageHeader.razor (Blazorise implementation)
└── PageToolbars/
└── BlazorisePageToolbarExtensions.cs (AddButton with ToolbarButton)
Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor (MudBlazor-Specific)
├── Depends on: Volo.Abp.AspNetCore.Components.Web.Theming ✓
├── Depends on: Volo.Abp.MudBlazorUI ✓
├── AbpAspNetCoreComponentsWebThemingMudBlazorModule.cs
├── Components/
│ └── PageHeader.razor (MudBlazor implementation)
└── PageToolbars/
└── MudBlazorPageToolbarExtensions.cs (AddButton with MudButton)
0.3 Updated Package Dependencies
Volo.Abp.AspNetCore.Components.Web.Theming.csproj (UI-Agnostic):
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- NO BlazoriseUI dependency! -->
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.Web\Volo.Abp.AspNetCore.Components.Web.csproj" />
<ProjectReference Include="..\Volo.Abp.UI.Navigation\Volo.Abp.UI.Navigation.csproj" />
</ItemGroup>
</Project>
Volo.Abp.AspNetCore.Components.Web.Theming.Blazorise.csproj:
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.Web.Theming\Volo.Abp.AspNetCore.Components.Web.Theming.csproj" />
<ProjectReference Include="..\Volo.Abp.BlazoriseUI\Volo.Abp.BlazoriseUI.csproj" />
</ItemGroup>
</Project>
Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.csproj:
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.Web.Theming\Volo.Abp.AspNetCore.Components.Web.Theming.csproj" />
<ProjectReference Include="..\Volo.Abp.MudBlazorUI\Volo.Abp.MudBlazorUI.csproj" />
</ItemGroup>
</Project>
0.4 Module Updates
AbpAspNetCoreComponentsWebThemingModule.cs (UI-Agnostic):
using Volo.Abp.AspNetCore.Components.Web;
using Volo.Abp.Modularity;
using Volo.Abp.UI.Navigation;
namespace Volo.Abp.AspNetCore.Components.Web.Theming;
[DependsOn(
typeof(AbpAspNetCoreComponentsWebModule), // NOT BlazoriseUI!
typeof(AbpUiNavigationModule)
)]
public class AbpAspNetCoreComponentsWebThemingModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpDynamicLayoutComponentOptions>(options =>
{
options.Components.Add(typeof(AbpAuthenticationState), null);
});
}
}
AbpAspNetCoreComponentsWebThemingBlazoriseModule.cs:
using Volo.Abp.BlazoriseUI;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.Blazorise;
[DependsOn(
typeof(AbpAspNetCoreComponentsWebThemingModule),
typeof(AbpBlazoriseUIModule)
)]
public class AbpAspNetCoreComponentsWebThemingBlazoriseModule : AbpModule
{
}
AbpAspNetCoreComponentsWebThemingMudBlazorModule.cs:
using Volo.Abp.MudBlazorUI;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor;
[DependsOn(
typeof(AbpAspNetCoreComponentsWebThemingModule),
typeof(AbpMudBlazorUIModule)
)]
public class AbpAspNetCoreComponentsWebThemingMudBlazorModule : AbpModule
{
}
0.5 Hosting-Specific Theming Packages
Apply the same pattern to hosting-specific packages:
BEFORE:
├── Volo.Abp.AspNetCore.Components.Server.Theming (depends on Blazorise.Bootstrap5)
├── Volo.Abp.AspNetCore.Components.WebAssembly.Theming (depends on Blazorise.Bootstrap5)
└── Volo.Abp.AspNetCore.Components.MauiBlazor.Theming (depends on Blazorise.Bootstrap5)
AFTER:
├── Volo.Abp.AspNetCore.Components.Server.Theming (UI-agnostic base)
├── Volo.Abp.AspNetCore.Components.Server.Theming.Blazorise (Blazorise-specific)
├── Volo.Abp.AspNetCore.Components.Server.Theming.MudBlazor (MudBlazor-specific)
│
├── Volo.Abp.AspNetCore.Components.WebAssembly.Theming (UI-agnostic base)
├── Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Blazorise (Blazorise-specific)
├── Volo.Abp.AspNetCore.Components.WebAssembly.Theming.MudBlazor (MudBlazor-specific)
│
├── Volo.Abp.AspNetCore.Components.MauiBlazor.Theming (UI-agnostic base)
├── Volo.Abp.AspNetCore.Components.MauiBlazor.Theming.Blazorise (Blazorise-specific)
└── Volo.Abp.AspNetCore.Components.MauiBlazor.Theming.MudBlazor (MudBlazor-specific)
Phase 1: MudBlazor Core Package
Objective: Create the core MudBlazor UI package that implements ABP's UI service interfaces.
1.1 Create Volo.Abp.MudBlazorUI
framework/src/Volo.Abp.MudBlazorUI/
├── Volo.Abp.MudBlazorUI.csproj
├── AbpMudBlazorUIModule.cs
├── MudBlazorUiMessageService.cs
├── MudBlazorUiNotificationService.cs
├── MudBlazorUiPageProgressService.cs
├── AbpMudCrudPageBase.cs
├── Components/
│ ├── AbpMudExtensibleDataGrid.razor
│ ├── AbpMudExtensibleDataGrid.razor.cs
│ ├── MudDataGridEntityActionsColumn.razor
│ ├── MudEntityAction.razor
│ ├── MudEntityActions.razor
│ ├── UiMessageAlert.razor
│ ├── UiNotificationAlert.razor
│ ├── UiPageProgress.razor
│ ├── MudSubmitButton.razor
│ ├── MudToolbarButton.razor
│ ├── MudPageAlert.razor
│ └── ObjectExtending/
│ ├── MudExtensionProperties.razor
│ ├── MudTextExtensionProperty.razor
│ ├── MudTextAreaExtensionProperty.razor
│ ├── MudCheckExtensionProperty.razor
│ ├── MudSelectExtensionProperty.razor
│ ├── MudDateTimeExtensionProperty.razor
│ ├── MudTimeExtensionProperty.razor
│ └── MudLookupExtensionProperty.razor
├── MudBlazorUiObjectExtensionPropertyInfoExtensions.cs
├── MudBlazorExtensionPropertyPolicyChecker.cs
└── wwwroot/
└── volo.abp.mudblazorui.css
1.2 Project File: Volo.Abp.MudBlazorUI.csproj
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Import Project="..\..\configureawait.props" />
<Import Project="..\..\common.props" />
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MudBlazor" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Components.Web\Volo.Abp.AspNetCore.Components.Web.csproj" />
<ProjectReference Include="..\Volo.Abp.Ddd.Application.Contracts\Volo.Abp.Ddd.Application.Contracts.csproj" />
<ProjectReference Include="..\Volo.Abp.Authorization\Volo.Abp.Authorization.csproj" />
<ProjectReference Include="..\Volo.Abp.GlobalFeatures\Volo.Abp.GlobalFeatures.csproj" />
<ProjectReference Include="..\Volo.Abp.Features\Volo.Abp.Features.csproj" />
</ItemGroup>
</Project>
1.3 Module Class: AbpMudBlazorUIModule.cs
using Microsoft.Extensions.DependencyInjection;
using MudBlazor.Services;
using Volo.Abp.AspNetCore.Components.Web;
using Volo.Abp.Authorization;
using Volo.Abp.Ddd.Application.Contracts;
using Volo.Abp.Features;
using Volo.Abp.GlobalFeatures;
using Volo.Abp.Modularity;
namespace Volo.Abp.MudBlazorUI;
[DependsOn(
typeof(AbpAspNetCoreComponentsWebModule),
typeof(AbpDddApplicationContractsModule),
typeof(AbpAuthorizationModule),
typeof(AbpGlobalFeaturesModule),
typeof(AbpFeaturesModule)
)]
public class AbpMudBlazorUIModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddMudServices(config =>
{
config.SnackbarConfiguration.PositionClass = Defaults.Classes.Position.BottomRight;
config.SnackbarConfiguration.PreventDuplicates = false;
config.SnackbarConfiguration.NewestOnTop = true;
config.SnackbarConfiguration.ShowCloseIcon = true;
config.SnackbarConfiguration.VisibleStateDuration = 5000;
});
}
}
1.4 Component Mapping (Blazorise → MudBlazor)
| Blazorise Component | MudBlazor Equivalent | Notes |
|---|---|---|
<DataGrid> |
<MudDataGrid> |
Different API for columns |
<Modal> |
<MudDialog> |
Uses IDialogService |
<Button> |
<MudButton> |
Similar API |
<TextEdit> |
<MudTextField> |
Different binding syntax |
<Select> |
<MudSelect> |
Similar API |
<Check> |
<MudCheckBox> |
Similar API |
<Snackbar> |
<MudSnackbar> |
Uses ISnackbar service |
<Card> |
<MudCard> |
Similar structure |
<Tabs> |
<MudTabs> |
Different panel syntax |
<Tooltip> |
<MudTooltip> |
Similar API |
<Field>/<FieldLabel> |
<MudField> |
MudBlazor uses labels differently |
<Validation> |
<MudForm> |
Different validation approach |
<Addons> |
<MudInputAdornment> |
For input decorations |
<Icon> |
<MudIcon> |
Uses Icons.* constants |
<Row>/<Column> |
<MudGrid>/<MudItem> |
Different grid system |
Phase 2: MudBlazor Theming Implementation
Objective: Create MudBlazor-specific theming packages using the refactored architecture.
2.1 Create Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor/
├── Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.csproj
├── AbpAspNetCoreComponentsWebThemingMudBlazorModule.cs
├── Components/
│ └── PageHeader.razor (MudBlazor implementation)
├── PageToolbars/
│ └── MudBlazorPageToolbarExtensions.cs
└── Themes/
├── AbpMudTheme.cs
└── AbpMudThemeProvider.razor
2.2 Create Hosting-Specific MudBlazor Theming Packages
Server:
framework/src/Volo.Abp.AspNetCore.Components.Server.Theming.MudBlazor/
├── Volo.Abp.AspNetCore.Components.Server.Theming.MudBlazor.csproj
├── AbpAspNetCoreComponentsServerThemingMudBlazorModule.cs
└── Bundling/
└── BlazorServerMudBlazorStyleContributor.cs
WebAssembly:
framework/src/Volo.Abp.AspNetCore.Components.WebAssembly.Theming.MudBlazor/
├── Volo.Abp.AspNetCore.Components.WebAssembly.Theming.MudBlazor.csproj
├── AbpAspNetCoreComponentsWebAssemblyThemingMudBlazorModule.cs
└── Bundling/
└── BlazorWebAssemblyMudBlazorStyleContributor.cs
MAUI Blazor:
framework/src/Volo.Abp.AspNetCore.Components.MauiBlazor.Theming.MudBlazor/
├── Volo.Abp.AspNetCore.Components.MauiBlazor.Theming.MudBlazor.csproj
├── AbpAspNetCoreComponentsMauiBlazorThemingMudBlazorModule.cs
└── Bundling/
└── MauiBlazorMudBlazorStyleContributor.cs
2.3 MudBlazor CSS Requirements
<!-- Required in _Host.cshtml or index.html -->
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
Phase 3: MudBlazor CRUD Page Base
Objective: Create MudBlazor version of AbpCrudPageBase with full CRUD functionality.
3.1 AbpMudCrudPageBase.cs
Located in Volo.Abp.MudBlazorUI:
public abstract class AbpMudCrudPageBase<TAppService, TEntityDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
: AbpComponentBase
where TAppService : ICrudAppService<TEntityDto, TKey, TGetListInput, TCreateInput, TUpdateInput>
where TEntityDto : IEntityDto<TKey>
where TGetListInput : new()
where TCreateInput : class, new()
where TUpdateInput : class, new()
{
[Inject] protected TAppService AppService { get; set; }
[Inject] protected IDialogService DialogService { get; set; }
[Inject] protected ISnackbar Snackbar { get; set; }
protected IReadOnlyList<TEntityDto> Entities { get; set; } = Array.Empty<TEntityDto>();
protected int TotalCount { get; set; }
protected int CurrentPage { get; set; } = 1;
protected int PageSize { get; set; } = 10;
protected TGetListInput GetListInput { get; set; } = new();
protected TCreateInput NewEntity { get; set; } = new();
protected TKey EditingEntityId { get; set; }
protected TUpdateInput EditingEntity { get; set; } = new();
// Permission properties
protected bool HasCreatePermission { get; set; }
protected bool HasUpdatePermission { get; set; }
protected bool HasDeletePermission { get; set; }
// Abstract methods for permissions
protected abstract string CreatePolicyName { get; }
protected abstract string UpdatePolicyName { get; }
protected abstract string DeletePolicyName { get; }
protected override async Task OnInitializedAsync()
{
await SetPermissionsAsync();
await GetEntitiesAsync();
}
protected virtual async Task SetPermissionsAsync()
{
HasCreatePermission = await AuthorizationService.IsGrantedAsync(CreatePolicyName);
HasUpdatePermission = await AuthorizationService.IsGrantedAsync(UpdatePolicyName);
HasDeletePermission = await AuthorizationService.IsGrantedAsync(DeletePolicyName);
}
protected virtual async Task GetEntitiesAsync()
{
var result = await AppService.GetListAsync(GetListInput);
Entities = result.Items;
TotalCount = (int)result.TotalCount;
}
protected virtual async Task CreateEntityAsync()
{
await AppService.CreateAsync(NewEntity);
Snackbar.Add(L["SuccessfullyCreated"], Severity.Success);
await GetEntitiesAsync();
}
protected virtual async Task UpdateEntityAsync()
{
await AppService.UpdateAsync(EditingEntityId, EditingEntity);
Snackbar.Add(L["SuccessfullyUpdated"], Severity.Success);
await GetEntitiesAsync();
}
protected virtual async Task DeleteEntityAsync(TEntityDto entity)
{
var confirmed = await DialogService.ShowMessageBox(
L["AreYouSure"],
L["AreYouSureToDelete"],
yesText: L["Yes"],
cancelText: L["Cancel"]);
if (confirmed == true)
{
await AppService.DeleteAsync(entity.Id);
Snackbar.Add(L["SuccessfullyDeleted"], Severity.Success);
await GetEntitiesAsync();
}
}
// ... additional CRUD methods
}
Phase 4: Feature Module MudBlazor Packages
Objective: Create MudBlazor versions of all ABP feature module UI packages.
4.1 Package Structure for Each Module
For each existing .Blazor module, create a corresponding MudBlazor package:
modules/identity/src/
├── Volo.Abp.Identity.Blazor/ # Existing (Blazorise) - DEPRECATED
├── Volo.Abp.Identity.Blazor.MudBlazor/ # New (MudBlazor)
│ ├── Volo.Abp.Identity.Blazor.MudBlazor.csproj
│ ├── AbpIdentityBlazorMudBlazorModule.cs
│ ├── Pages/Identity/
│ │ ├── UserManagement.razor
│ │ ├── UserManagement.razor.cs
│ │ ├── RoleManagement.razor
│ │ └── RoleManagement.razor.cs
│ └── _Imports.razor
├── Volo.Abp.Identity.Blazor.MudBlazor.Server/
│ ├── Volo.Abp.Identity.Blazor.MudBlazor.Server.csproj
│ └── AbpIdentityBlazorMudBlazorServerModule.cs
└── Volo.Abp.Identity.Blazor.MudBlazor.WebAssembly/
├── Volo.Abp.Identity.Blazor.MudBlazor.WebAssembly.csproj
└── AbpIdentityBlazorMudBlazorWebAssemblyModule.cs
4.2 Complete Module List
| Current Package (Blazorise) | New Package (MudBlazor) |
|---|---|
Volo.Abp.Identity.Blazor |
Volo.Abp.Identity.Blazor.MudBlazor |
Volo.Abp.Identity.Blazor.Server |
Volo.Abp.Identity.Blazor.MudBlazor.Server |
Volo.Abp.Identity.Blazor.WebAssembly |
Volo.Abp.Identity.Blazor.MudBlazor.WebAssembly |
Volo.Abp.TenantManagement.Blazor |
Volo.Abp.TenantManagement.Blazor.MudBlazor |
Volo.Abp.TenantManagement.Blazor.Server |
Volo.Abp.TenantManagement.Blazor.MudBlazor.Server |
Volo.Abp.TenantManagement.Blazor.WebAssembly |
Volo.Abp.TenantManagement.Blazor.MudBlazor.WebAssembly |
Volo.Abp.PermissionManagement.Blazor |
Volo.Abp.PermissionManagement.Blazor.MudBlazor |
Volo.Abp.PermissionManagement.Blazor.Server |
Volo.Abp.PermissionManagement.Blazor.MudBlazor.Server |
Volo.Abp.PermissionManagement.Blazor.WebAssembly |
Volo.Abp.PermissionManagement.Blazor.MudBlazor.WebAssembly |
Volo.Abp.FeatureManagement.Blazor |
Volo.Abp.FeatureManagement.Blazor.MudBlazor |
Volo.Abp.FeatureManagement.Blazor.Server |
Volo.Abp.FeatureManagement.Blazor.MudBlazor.Server |
Volo.Abp.FeatureManagement.Blazor.WebAssembly |
Volo.Abp.FeatureManagement.Blazor.MudBlazor.WebAssembly |
Volo.Abp.SettingManagement.Blazor |
Volo.Abp.SettingManagement.Blazor.MudBlazor |
Volo.Abp.SettingManagement.Blazor.Server |
Volo.Abp.SettingManagement.Blazor.MudBlazor.Server |
Volo.Abp.SettingManagement.Blazor.WebAssembly |
Volo.Abp.SettingManagement.Blazor.MudBlazor.WebAssembly |
Volo.Abp.Account.Blazor |
Volo.Abp.Account.Blazor.MudBlazor |
4.3 Example: UserManagement.razor (MudBlazor)
@page "/identity/users"
@attribute [Authorize(IdentityPermissions.Users.Default)]
@using Microsoft.AspNetCore.Authorization
@using Volo.Abp.Identity.Localization
@inherits AbpMudCrudPageBase<IIdentityUserAppService, IdentityUserDto, Guid, GetIdentityUsersInput, IdentityUserCreateDto, IdentityUserUpdateDto>
<MudCard>
<MudCardHeader>
<CardHeaderContent>
<MudText Typo="Typo.h5">@L["Users"]</MudText>
</CardHeaderContent>
<CardHeaderActions>
@if (HasCreatePermission)
{
<MudButton Variant="Variant.Filled"
Color="Color.Primary"
OnClick="@OpenCreateDialog">
@L["NewUser"]
</MudButton>
}
</CardHeaderActions>
</MudCardHeader>
<MudCardContent>
<MudTextField @bind-Value="GetListInput.Filter"
Label="@L["Search"]"
Adornment="Adornment.Start"
AdornmentIcon="@Icons.Material.Filled.Search"
OnKeyUp="@OnSearchKeyUp" />
<MudDataGrid Items="@Entities"
T="IdentityUserDto"
SortMode="SortMode.Single"
Filterable="false"
Dense="true">
<Columns>
<PropertyColumn Property="x => x.UserName" Title="@L["UserName"]" />
<PropertyColumn Property="x => x.Email" Title="@L["Email"]" />
<PropertyColumn Property="x => x.PhoneNumber" Title="@L["PhoneNumber"]" />
<TemplateColumn Title="@L["Actions"]">
<CellTemplate>
<MudMenu Icon="@Icons.Material.Filled.MoreVert">
@if (HasUpdatePermission)
{
<MudMenuItem OnClick="@(() => OpenEditDialog(context.Item))">
@L["Edit"]
</MudMenuItem>
}
@if (HasDeletePermission)
{
<MudMenuItem OnClick="@(() => DeleteEntityAsync(context.Item))">
@L["Delete"]
</MudMenuItem>
}
</MudMenu>
</CellTemplate>
</TemplateColumn>
</Columns>
<PagerContent>
<MudDataGridPager T="IdentityUserDto" />
</PagerContent>
</MudDataGrid>
</MudCardContent>
</MudCard>
Phase 5: MudBlazor Basic Theme
Objective: Create MudBlazor-based theme to replace Blazorise BasicTheme.
5.1 Theme Package Structure
modules/basic-theme/src/
├── Volo.Abp.AspNetCore.Components.Web.BasicTheme/ # Existing (Blazorise) - DEPRECATED
├── Volo.Abp.AspNetCore.Components.Server.BasicTheme/ # DEPRECATED
├── Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/ # DEPRECATED
│
├── Volo.Abp.AspNetCore.Components.Web.MudBlazorBasicTheme/ # New (MudBlazor)
│ ├── Volo.Abp.AspNetCore.Components.Web.MudBlazorBasicTheme.csproj
│ ├── AbpAspNetCoreComponentsWebMudBlazorBasicThemeModule.cs
│ ├── Themes/Basic/
│ │ ├── MainLayout.razor
│ │ ├── NavMenu.razor
│ │ ├── LoginDisplay.razor
│ │ └── Branding.razor
│ └── wwwroot/
│ └── themes/basic/
│ └── main.css
├── Volo.Abp.AspNetCore.Components.Server.MudBlazorBasicTheme/
│ ├── Volo.Abp.AspNetCore.Components.Server.MudBlazorBasicTheme.csproj
│ └── AbpAspNetCoreComponentsServerMudBlazorBasicThemeModule.cs
└── Volo.Abp.AspNetCore.Components.WebAssembly.MudBlazorBasicTheme/
├── Volo.Abp.AspNetCore.Components.WebAssembly.MudBlazorBasicTheme.csproj
└── AbpAspNetCoreComponentsWebAssemblyMudBlazorBasicThemeModule.cs
5.2 Example: MainLayout.razor (MudBlazor)
@inherits LayoutComponentBase
<MudThemeProvider />
<MudPopoverProvider />
<MudDialogProvider />
<MudSnackbarProvider />
<MudLayout>
<MudAppBar Elevation="1">
<MudIconButton Icon="@Icons.Material.Filled.Menu"
Color="Color.Inherit"
Edge="Edge.Start"
OnClick="@ToggleDrawer" />
<Branding />
<MudSpacer />
<LoginDisplay />
</MudAppBar>
<MudDrawer @bind-Open="@_drawerOpen"
Elevation="1"
Variant="@DrawerVariant.Mini">
<NavMenu />
</MudDrawer>
<MudMainContent>
<MudContainer MaxWidth="MaxWidth.False" Class="pa-4">
<UiPageProgress />
<UiMessageAlert />
<UiNotificationAlert />
@Body
</MudContainer>
</MudMainContent>
</MudLayout>
@code {
private bool _drawerOpen = true;
private void ToggleDrawer()
{
_drawerOpen = !_drawerOpen;
}
}
Phase 6: Update Application Templates
Objective: Make MudBlazor the default for new projects, with Blazorise as deprecated option.
6.1 CLI Changes
# New default (MudBlazor)
abp new MyApp -t app --ui blazor
# Legacy option (deprecated, shows warning)
abp new MyApp -t app --ui blazor --blazor-ui-framework blazorise
6.2 Template Updates
Update all Blazor templates to use MudBlazor packages:
<!-- Default package references in templates -->
<ItemGroup>
<PackageReference Include="Volo.Abp.MudBlazorUI" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.Identity.Blazor.MudBlazor" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.TenantManagement.Blazor.MudBlazor" Version="$(AbpVersion)" />
<!-- etc. -->
</ItemGroup>
6.3 Deprecation Warning
When --blazor-ui-framework blazorise is used:
WARNING: Blazorise UI framework is deprecated and will be removed in ABP v12.0.
Please use MudBlazor (default) for new projects.
See migration guide: https://docs.abp.io/en/abp/latest/UI/Blazor/Migration-Blazorise-To-MudBlazor
Phase 7: Documentation & Migration Guides
Objective: Comprehensive documentation for migration and MudBlazor usage.
7.1 Documentation Structure
docs/en/
├── UI/
│ └── Blazor/
│ ├── Overall.md # Updated - MudBlazor focus
│ ├── Getting-Started.md # MudBlazor setup
│ ├── Components.md # MudBlazor components
│ ├── Theming.md # MudBlazor theming
│ ├── CRUD-Pages.md # AbpMudCrudPageBase
│ ├── Migration-From-Blazorise.md # Migration guide
│ └── Blazorise/ # Legacy docs (deprecated)
│ └── Index.md
7.2 Migration Guide Contents
-
Component Migration Reference
- Complete mapping of Blazorise → MudBlazor components
- Code examples for each component type
-
Service Migration
IDialogServiceusage (replaces Modal pattern)ISnackbarusage (replaces Snackbar pattern)
-
Validation Migration
- Blazorise
<Validation>→ MudBlazor<MudForm> - Data annotation handling differences
- Blazorise
-
CSS/Styling Migration
- Blazorise CSS classes → MudBlazor classes
- Theme customization differences
-
Step-by-Step Migration
- Update package references
- Update module dependencies
- Update component markup
- Update code-behind files
- Test and verify
Phase 8: Remove Blazorise Packages
Objective: Complete removal of Blazorise from ABP Framework.
8.1 Packages to Remove
Framework Packages:
Volo.Abp.BlazoriseUIVolo.Abp.AspNetCore.Components.Web.Theming.BlazoriseVolo.Abp.AspNetCore.Components.Server.Theming.BlazoriseVolo.Abp.AspNetCore.Components.WebAssembly.Theming.BlazoriseVolo.Abp.AspNetCore.Components.MauiBlazor.Theming.Blazorise
Module Packages:
Volo.Abp.Identity.BlazorVolo.Abp.Identity.Blazor.ServerVolo.Abp.Identity.Blazor.WebAssemblyVolo.Abp.TenantManagement.BlazorVolo.Abp.TenantManagement.Blazor.ServerVolo.Abp.TenantManagement.Blazor.WebAssemblyVolo.Abp.PermissionManagement.BlazorVolo.Abp.PermissionManagement.Blazor.ServerVolo.Abp.PermissionManagement.Blazor.WebAssemblyVolo.Abp.FeatureManagement.BlazorVolo.Abp.FeatureManagement.Blazor.ServerVolo.Abp.FeatureManagement.Blazor.WebAssemblyVolo.Abp.SettingManagement.BlazorVolo.Abp.SettingManagement.Blazor.ServerVolo.Abp.SettingManagement.Blazor.WebAssemblyVolo.Abp.Account.Blazor
Theme Packages:
Volo.Abp.AspNetCore.Components.Web.BasicThemeVolo.Abp.AspNetCore.Components.Server.BasicThemeVolo.Abp.AspNetCore.Components.WebAssembly.BasicTheme
8.2 Removal Timeline
| ABP Version | Action |
|---|---|
| v10.x | Phase 0: Refactor theming architecture |
| v10.x | Phases 1-5: MudBlazor packages introduced, Blazorise fully supported |
| v11.0 | Phase 6-7: MudBlazor default in templates, Blazorise deprecated |
| v12.0 | Phase 8: Blazorise packages removed |
New Packages Summary
Framework Packages (framework/src/)
| Package | Description |
|---|---|
Volo.Abp.MudBlazorUI |
Core MudBlazor UI module (replaces BlazoriseUI) |
Volo.Abp.AspNetCore.Components.Web.Theming |
UI-agnostic theming base (refactored) |
Volo.Abp.AspNetCore.Components.Web.Theming.Blazorise |
Blazorise theming (new, split from Web.Theming) |
Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor |
MudBlazor theming |
Volo.Abp.AspNetCore.Components.Server.Theming |
UI-agnostic server theming (refactored) |
Volo.Abp.AspNetCore.Components.Server.Theming.Blazorise |
Blazorise server theming |
Volo.Abp.AspNetCore.Components.Server.Theming.MudBlazor |
MudBlazor server theming |
Volo.Abp.AspNetCore.Components.WebAssembly.Theming |
UI-agnostic WASM theming (refactored) |
Volo.Abp.AspNetCore.Components.WebAssembly.Theming.Blazorise |
Blazorise WASM theming |
Volo.Abp.AspNetCore.Components.WebAssembly.Theming.MudBlazor |
MudBlazor WASM theming |
Volo.Abp.AspNetCore.Components.MauiBlazor.Theming |
UI-agnostic MAUI theming (refactored) |
Volo.Abp.AspNetCore.Components.MauiBlazor.Theming.Blazorise |
Blazorise MAUI theming |
Volo.Abp.AspNetCore.Components.MauiBlazor.Theming.MudBlazor |
MudBlazor MAUI theming |
Module Packages (modules/)
| Package | Description |
|---|---|
Volo.Abp.Identity.Blazor.MudBlazor |
Identity management UI |
Volo.Abp.Identity.Blazor.MudBlazor.Server |
Identity Server hosting |
Volo.Abp.Identity.Blazor.MudBlazor.WebAssembly |
Identity WASM hosting |
Volo.Abp.TenantManagement.Blazor.MudBlazor |
Tenant management UI |
Volo.Abp.TenantManagement.Blazor.MudBlazor.Server |
Tenant Server hosting |
Volo.Abp.TenantManagement.Blazor.MudBlazor.WebAssembly |
Tenant WASM hosting |
Volo.Abp.PermissionManagement.Blazor.MudBlazor |
Permission management UI |
Volo.Abp.PermissionManagement.Blazor.MudBlazor.Server |
Permission Server hosting |
Volo.Abp.PermissionManagement.Blazor.MudBlazor.WebAssembly |
Permission WASM hosting |
Volo.Abp.FeatureManagement.Blazor.MudBlazor |
Feature management UI |
Volo.Abp.FeatureManagement.Blazor.MudBlazor.Server |
Feature Server hosting |
Volo.Abp.FeatureManagement.Blazor.MudBlazor.WebAssembly |
Feature WASM hosting |
Volo.Abp.SettingManagement.Blazor.MudBlazor |
Setting management UI |
Volo.Abp.SettingManagement.Blazor.MudBlazor.Server |
Setting Server hosting |
Volo.Abp.SettingManagement.Blazor.MudBlazor.WebAssembly |
Setting WASM hosting |
Volo.Abp.Account.Blazor.MudBlazor |
Account UI |
Theme Packages (modules/basic-theme/)
| Package | Description |
|---|---|
Volo.Abp.AspNetCore.Components.Web.MudBlazorBasicTheme |
Basic theme for MudBlazor |
Volo.Abp.AspNetCore.Components.Server.MudBlazorBasicTheme |
Server hosting |
Volo.Abp.AspNetCore.Components.WebAssembly.MudBlazorBasicTheme |
WASM hosting |
Package Dependency Diagram (Refactored)
┌─────────────────────────────────────┐
│ Volo.Abp.AspNetCore.Components.Web │
│ (UI-Agnostic) │
│ - IUiMessageService │
│ - IUiNotificationService │
│ - IUiPageProgressService │
│ - BreadcrumbItem (moved here) │
└─────────────────┬───────────────────┘
│
┌─────────────────┴───────────────────┐
│ │
▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ Volo.Abp.BlazoriseUI│ │ Volo.Abp.MudBlazorUI│
│ (Blazorise Impl) │ │ (MudBlazor Impl) │
└──────────┬──────────┘ └──────────┬──────────┘
│ │
│ ┌──────────────────────────┐ │
│ │ ...Web.Theming │ │
│ │ (UI-Agnostic Base) │ │
│ │ - IThemeManager │ │
│ │ - PageToolbars │ │
│ │ - Toolbars │ │
│ └────────────┬─────────────┘ │
│ │ │
▼ │ ▼
┌─────────────────────┐ │ ┌─────────────────────┐
│ ...Web.Theming │◄─────┴─────►│ ...Web.Theming │
│ .Blazorise │ │ .MudBlazor │
│ (Blazorise Theme) │ │ (MudBlazor Theme) │
└──────────┬──────────┘ └──────────┬──────────┘
│ │
▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ Identity.Blazor │ │ Identity.Blazor │
│ (Blazorise) │ │ .MudBlazor │
│ DEPRECATED │ │ │
└─────────────────────┘ └─────────────────────┘
Success Criteria
- Phase 0 complete: Theming architecture refactored to be UI-agnostic
- All MudBlazor packages created and functional
- Feature parity with existing Blazorise implementations
- Templates default to MudBlazor
- Comprehensive migration documentation
- Blazorise packages deprecated with clear timeline
- Blazorise packages removed in final phase
Risk Assessment
| Risk | Mitigation |
|---|---|
| Breaking changes during Phase 0 refactoring | Careful API preservation, deprecation notices |
| User migration difficulty | Detailed migration guide, code examples |
| MudBlazor breaking changes | Pin to specific versions, test thoroughly |
| Missing MudBlazor features | Document gaps, provide workarounds |
| Performance differences | Benchmark and optimize |
| Community resistance | Clear communication, sufficient deprecation period |
Conclusion
This migration plan provides a clear path from Blazorise to MudBlazor as the sole UI component library in ABP Framework. The key improvement is Phase 0, which refactors the theming architecture to be UI-agnostic, enabling clean separation between:
Volo.Abp.AspNetCore.Components.Web.Theming- UI-agnostic (interfaces, options, base classes)Volo.Abp.AspNetCore.Components.Web.Theming.Blazorise- Blazorise-specific implementationsVolo.Abp.AspNetCore.Components.Web.Theming.MudBlazor- MudBlazor-specific implementations
This architecture allows both UI frameworks to coexist during the transition period while sharing common theming infrastructure.