# 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 implementations
- `Volo.Abp.AspNetCore.Components.Web.Theming` - Theming infrastructure (currently depends on BlazoriseUI - **this needs to change**)
**Hosting-Specific Packages:**
- `Volo.Abp.AspNetCore.Components.Server.Theming`
- `Volo.Abp.AspNetCore.Components.WebAssembly.Theming`
- `Volo.Abp.AspNetCore.Components.MauiBlazor.Theming`
**Feature Module Packages (using Blazorise components):**
- `Volo.Abp.Identity.Blazor`
- `Volo.Abp.TenantManagement.Blazor`
- `Volo.Abp.PermissionManagement.Blazor`
- `Volo.Abp.FeatureManagement.Blazor`
- `Volo.Abp.SettingManagement.Blazor`
- `Volo.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 notifications
- `IUiPageProgressService` - 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:
1. `BreadcrumbItem` class - A simple POCO that should be UI-agnostic
2. `PageHeader.razor` - Uses Blazorise components directly (should be moved)
3. `PageToolbarExtensions.AddButton` - Uses Blazorise `ToolbarButton` (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):
```csharp
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):
```xml
net10.0
```
**`Volo.Abp.AspNetCore.Components.Web.Theming.Blazorise.csproj`**:
```xml
net10.0
```
**`Volo.Abp.AspNetCore.Components.Web.Theming.MudBlazor.csproj`**:
```xml
net10.0
```
### 0.4 Module Updates
**`AbpAspNetCoreComponentsWebThemingModule.cs`** (UI-Agnostic):
```csharp
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(options =>
{
options.Components.Add(typeof(AbpAuthenticationState), null);
});
}
}
```
**`AbpAspNetCoreComponentsWebThemingBlazoriseModule.cs`**:
```csharp
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`**:
```csharp
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`
```xml
net10.0
```
### 1.3 Module Class: `AbpMudBlazorUIModule.cs`
```csharp
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 |
|---------------------|----------------------|-------|
| `` | `` | Different API for columns |
| `` | `` | Uses `IDialogService` |
| `