.NET MAUI 10, released alongside .NET 10, delivers the most significant update to Microsoft’s cross-platform UI framework since its initial release. With enhanced Blazor Hybrid capabilities, native on-device AI integration, and dramatically improved startup performance, MAUI 10 positions itself as a serious contender for enterprise cross-platform development. This comprehensive guide explores the new features, architectural patterns, and best practices for building production applications targeting iOS, Android, macOS, and Windows from a single C# codebase.
What’s New in .NET MAUI 10
| Feature | MAUI 9 | MAUI 10 |
|---|---|---|
| Startup Time (Android) | ~800ms | ~400ms (50% faster) |
| Blazor Hybrid | WebView-based | Native rendering option |
| AI Integration | Manual SDK integration | Built-in Microsoft.Extensions.AI |
| Native AOT | iOS only | All platforms |
| Hot Reload | XAML + C# (partial) | Full support including handlers |
| Accessibility | Basic support | Enhanced screen reader, semantic properties |
| Foldable Devices | Limited | Full hinge and fold APIs |
MAUI 10 Architecture
graph TB
subgraph App ["Your MAUI Application"]
UI["UI Layer (XAML/Blazor)"]
VM["ViewModels (MVVM)"]
Services["Services & Business Logic"]
AI["AI Services"]
end
subgraph MAUI ["MAUI Framework"]
Handlers["Platform Handlers"]
Graphics["MAUI Graphics"]
Essentials["MAUI Essentials"]
end
subgraph Platforms ["Native Platforms"]
iOS["iOS / macOS (Catalyst)"]
Android["Android"]
Windows["Windows (WinUI 3)"]
end
UI --> VM
VM --> Services
Services --> AI
UI --> Handlers
Handlers --> iOS
Handlers --> Android
Handlers --> Windows
Services --> Essentials
style UI fill:#E8F5E9,stroke:#2E7D32
style AI fill:#E3F2FD,stroke:#1565C0
style Handlers fill:#FFF3E0,stroke:#EF6C00
Getting Started with MAUI 10
# Install/update MAUI workload
dotnet workload install maui
# Create a new MAUI application
dotnet new maui -n MyMauiApp
cd MyMauiApp
# Or create a Blazor Hybrid app
dotnet new maui-blazor -n MyHybridApp
# Run on different platforms
dotnet build -t:Run -f net10.0-android
dotnet build -t:Run -f net10.0-ios
dotnet build -t:Run -f net10.0-maccatalyst
dotnet build -t:Run -f net10.0-windows10.0.19041.0
Blazor Hybrid: Native Performance with Web UI
Blazor Hybrid combines Blazor’s component model with native platform capabilities. MAUI 10 introduces an optional native rendering mode that bypasses the WebView for specific components:
// MauiProgram.cs - Configure Blazor Hybrid
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
// Add Blazor WebView
builder.Services.AddMauiBlazorWebView();
#if DEBUG
builder.Services.AddBlazorWebViewDeveloperTools();
#endif
// Configure native rendering for specific components (new in MAUI 10)
builder.Services.AddBlazorHybridNativeRendering(options =>
{
options.EnableNativeRendering = true;
options.NativeComponents = new[]
{
typeof(NativeMapComponent),
typeof(NativeCameraComponent),
typeof(NativeChartComponent)
};
});
// Register services
builder.Services.AddSingleton<IDataService, DataService>();
builder.Services.AddSingleton<IAiService, AiService>();
return builder.Build();
}
Sharing Components Between Web and Mobile
@* ProductCard.razor - Works in Blazor Web AND MAUI Blazor Hybrid *@
@inject IProductService ProductService
<div class="product-card @(IsCompact ? "compact" : "")">
<img src="@Product.ImageUrl" alt="@Product.Name" />
<h3>@Product.Name</h3>
<p class="price">@Product.Price.ToString("C")</p>
@if (ShowDetails)
{
<p class="description">@Product.Description</p>
<div class="rating">
@for (int i = 0; i < Product.Rating; i++)
{
<span class="star filled">★</span>
}
</div>
}
<button class="btn-primary" @onclick="AddToCart">
Add to Cart
</button>
</div>
@code {
[Parameter] public Product Product { get; set; } = default!;
[Parameter] public bool ShowDetails { get; set; } = true;
[Parameter] public bool IsCompact { get; set; }
private async Task AddToCart()
{
await ProductService.AddToCartAsync(Product.Id);
}
}
On-Device AI Integration
MAUI 10 integrates with Microsoft.Extensions.AI and platform-specific AI capabilities for on-device inference:
// Register AI services in MauiProgram.cs
builder.Services.AddOnDeviceAI(options =>
{
options.EnableTextGeneration = true;
options.EnableImageClassification = true;
options.EnableSpeechRecognition = true;
options.ModelCachePath = FileSystem.CacheDirectory;
});
// AI Service implementation
public class AiService : IAiService
{
private readonly IOnDeviceTextGenerator _textGenerator;
private readonly IImageClassifier _imageClassifier;
public AiService(
IOnDeviceTextGenerator textGenerator,
IImageClassifier imageClassifier)
{
_textGenerator = textGenerator;
_imageClassifier = imageClassifier;
}
public async Task<string> GenerateProductDescriptionAsync(Product product)
{
// Uses on-device small language model (no internet required)
var prompt = $"Write a compelling product description for: {product.Name}";
return await _textGenerator.GenerateAsync(prompt, maxTokens: 150);
}
public async Task<IReadOnlyList<ClassificationResult>> ClassifyImageAsync(Stream imageStream)
{
// On-device image classification
return await _imageClassifier.ClassifyAsync(imageStream);
}
}
// Using AI in a page
public partial class ProductScanPage : ContentPage
{
private readonly IAiService _aiService;
public ProductScanPage(IAiService aiService)
{
_aiService = aiService;
InitializeComponent();
}
private async void OnCameraFrameCaptured(object sender, CameraFrameEventArgs e)
{
var results = await _aiService.ClassifyImageAsync(e.Frame);
if (results.Any(r => r.Confidence > 0.85))
{
var topResult = results.First();
await DisplayAlert("Product Found",
$"Detected: {topResult.Label} ({topResult.Confidence:P0})", "OK");
}
}
}
On-device AI works offline, reduces latency to milliseconds, and keeps sensitive data on the device—critical for healthcare, finance, and privacy-conscious applications.
MVVM with CommunityToolkit.Mvvm
The recommended MVVM approach uses source generators for boilerplate-free ViewModels:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
public partial class ProductListViewModel : ObservableObject
{
private readonly IProductService _productService;
private readonly IAiService _aiService;
public ProductListViewModel(IProductService productService, IAiService aiService)
{
_productService = productService;
_aiService = aiService;
}
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(HasProducts))]
private ObservableCollection<Product> _products = new();
[ObservableProperty]
private bool _isLoading;
[ObservableProperty]
private string _searchQuery = string.Empty;
public bool HasProducts => Products.Count > 0;
[RelayCommand]
private async Task LoadProductsAsync()
{
try
{
IsLoading = true;
var products = await _productService.GetProductsAsync();
Products.Clear();
foreach (var product in products)
{
Products.Add(product);
}
}
finally
{
IsLoading = false;
}
}
[RelayCommand]
private async Task SearchAsync()
{
if (string.IsNullOrWhiteSpace(SearchQuery)) return;
IsLoading = true;
var results = await _productService.SearchAsync(SearchQuery);
Products.Clear();
foreach (var product in results)
{
Products.Add(product);
}
IsLoading = false;
}
[RelayCommand]
private async Task GenerateDescriptionAsync(Product product)
{
var description = await _aiService.GenerateProductDescriptionAsync(product);
product.Description = description;
}
}
Native AOT Compilation
MAUI 10 extends Native AOT support to all platforms for smaller binaries and faster startup:
<!-- In your .csproj file -->
<PropertyGroup>
<TargetFrameworks>net10.0-android;net10.0-ios;net10.0-maccatalyst;net10.0-windows10.0.19041.0</TargetFrameworks>
<!-- Enable Native AOT for release builds -->
<PublishAot Condition="'$(Configuration)' == 'Release'">true</PublishAot>
<!-- Trim unused code -->
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>partial</TrimMode>
<!-- Android-specific AOT -->
<AndroidEnableProfiledAot Condition="'$(Configuration)' == 'Release'">true</AndroidEnableProfiledAot>
<!-- iOS-specific -->
<MtouchInterpreter Condition="'$(Configuration)' == 'Release'">-all</MtouchInterpreter>
</PropertyGroup>
| Metric | Without AOT | With Native AOT | Improvement |
|---|---|---|---|
| Android APK Size | 45 MB | 28 MB | 38% smaller |
| iOS App Size | 62 MB | 41 MB | 34% smaller |
| Android Startup | 800ms | 400ms | 50% faster |
| iOS Startup | 450ms | 280ms | 38% faster |
Platform-Specific Features
// Access platform-specific APIs safely
public partial class DeviceService
{
// Partial method implemented per platform
public partial string GetDeviceModel();
public partial Task<bool> AuthenticateWithBiometricsAsync();
}
// Platforms/Android/DeviceService.cs
public partial class DeviceService
{
public partial string GetDeviceModel() =>
$"{Android.OS.Build.Manufacturer} {Android.OS.Build.Model}";
public partial async Task<bool> AuthenticateWithBiometricsAsync()
{
var biometricManager = BiometricManager.From(Platform.CurrentActivity!);
var canAuthenticate = biometricManager.CanAuthenticate(
BiometricManager.Authenticators.BiometricStrong);
if (canAuthenticate != BiometricManager.BiometricSuccess)
return false;
// Use BiometricPrompt for authentication
// ...
return true;
}
}
// Platforms/iOS/DeviceService.cs
public partial class DeviceService
{
public partial string GetDeviceModel() =>
UIKit.UIDevice.CurrentDevice.Model;
public partial async Task<bool> AuthenticateWithBiometricsAsync()
{
var context = new LocalAuthentication.LAContext();
var canEvaluate = context.CanEvaluatePolicy(
LocalAuthentication.LAPolicy.DeviceOwnerAuthenticationWithBiometrics,
out _);
if (!canEvaluate) return false;
var (success, _) = await context.EvaluatePolicyAsync(
LocalAuthentication.LAPolicy.DeviceOwnerAuthenticationWithBiometrics,
"Authenticate to continue");
return success;
}
}
Foldable Device Support
// Respond to device folding/unfolding
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
// Subscribe to fold state changes
DeviceDisplay.FoldStateChanged += OnFoldStateChanged;
}
private void OnFoldStateChanged(object? sender, FoldStateChangedEventArgs e)
{
switch (e.FoldState)
{
case FoldState.Flat:
// Device is fully open - show two-pane layout
MasterPane.IsVisible = true;
DetailPane.IsVisible = true;
break;
case FoldState.HalfOpened:
// Device is partially folded - adjust layout
MasterPane.IsVisible = true;
DetailPane.IsVisible = false;
break;
case FoldState.Closed:
// Device is closed - single pane
MasterPane.IsVisible = false;
DetailPane.IsVisible = true;
break;
}
}
}
MAUI 10’s foldable support targets Samsung Galaxy Z Fold/Flip, Microsoft Surface Duo, and other Android foldables. Test with the Android Emulator’s foldable device profiles.
Testing MAUI Applications
// UI testing with Appium and .NET
public class ProductListTests : BaseTest
{
[Test]
public async Task ProductList_LoadsProducts_DisplaysInList()
{
// Arrange
await NavigateToPage("Products");
// Act
await WaitForElement("ProductList");
var products = await FindElements("ProductCard");
// Assert
Assert.That(products.Count, Is.GreaterThan(0));
}
[Test]
public async Task ProductCard_TapAddToCart_ShowsConfirmation()
{
// Arrange
await NavigateToPage("Products");
var firstProduct = await FindElement("ProductCard[0]");
// Act
var addButton = await firstProduct.FindElement("AddToCartButton");
await addButton.ClickAsync();
// Assert
var toast = await WaitForElement("ToastNotification");
Assert.That(await toast.GetTextAsync(), Does.Contain("Added to cart"));
}
}
Key Takeaways
- .NET MAUI 10 delivers 50% faster startup on Android and significant improvements across all platforms.
- Blazor Hybrid enables sharing UI components between web and mobile, with optional native rendering for performance-critical components.
- On-device AI integration works offline with low latency, supporting text generation, image classification, and speech recognition.
- Native AOT compilation is now available on all platforms, reducing app size by 35-40% and improving startup times.
- Foldable device support lets you build adaptive UIs for the growing market of foldable Android devices.
Conclusion
.NET MAUI 10 addresses the performance and feature gaps that held back earlier versions. The combination of Blazor Hybrid for code sharing, on-device AI for intelligent features, and Native AOT for fast startup creates a compelling platform for enterprise mobile development. For organizations already invested in .NET, MAUI 10 offers a productive path to cross-platform mobile and desktop applications without maintaining separate iOS, Android, and Windows codebases.
References
- .NET MAUI Documentation
- Announcing .NET MAUI 10
- Blazor Hybrid Documentation
- .NET MAUI GitHub Repository
Discover more from C4: Container, Code, Cloud & Context
Subscribe to get the latest posts sent to your email.