.NET MAUI trong 2026: Phát triển Cross-Platform và Câu hỏi Phỏng vấn
Hướng dẫn .NET MAUI toàn diện về phát triển cross-platform với .NET 10, handler architecture, MVVM, HybridWebView và các câu hỏi phỏng vấn quan trọng năm 2026.

.NET MAUI (Multi-platform App UI) đã trưởng thành thành một framework cross-platform sẵn sàng cho production với .NET 10. Là phiên bản Long-Term Support được hỗ trợ đến tháng 11 năm 2028, .NET MAUI 10 được phân phối dưới dạng workload và gói NuGet, mang đến cải thiện về chất lượng, hiệu năng và các API mới như nâng cấp HybridWebView và SafeAreaEdges. Bài hướng dẫn này trình bày cách xây dựng ứng dụng cross-platform, kiến trúc đằng sau MAUI, và các câu hỏi phỏng vấn mà nhà tuyển dụng thường đặt ra trong năm 2026.
.NET 10 là bản phát hành Long-Term Support (được hỗ trợ đến tháng 11 năm 2028). MAUI 10 tập trung vào chất lượng và hiệu năng thay vì các control UI mới — biến nó thành bản phát hành MAUI ổn định nhất từ trước đến nay. Framework hiện được cung cấp dưới dạng workload .NET và gói NuGet, cho phép ghim phiên bản theo từng dự án.
Thiết lập Dự án .NET MAUI 10 từ Đầu
Cách nhanh nhất để có một ứng dụng MAUI hoạt động bắt đầu với .NET CLI. .NET 10 giới thiệu template dự án cập nhật bao gồm service defaults .NET Aspire, kết nối telemetry và service discovery ngay từ đầu.
# Cài đặt workload MAUI (nếu chưa có)
dotnet workload install maui
# Tạo ứng dụng MAUI mới
dotnet new maui -n CrossPlatformDemo
cd CrossPlatformDemo
# Chạy trên emulator Android
dotnet build -t:Run -f net10.0-androidCấu trúc single-project hợp nhất mã platform-specific vào thư mục Platforms/ trong khi chia sẻ phần còn lại. File MauiProgram.cs đóng vai trò composition root — nơi đăng ký service, font và handler.
using Microsoft.Extensions.Logging;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
// Đăng ký service cho dependency injection
builder.Services.AddSingleton<IApiService, ApiService>();
builder.Services.AddTransient<MainViewModel>();
#if DEBUG
builder.Logging.AddDebug();
#endif
return builder.Build();
}
}Dependency injection trong MAUI tuân theo cùng mô hình với ASP.NET Core. Service Singleton tồn tại suốt vòng đời ứng dụng, service Transient được tạo mới mỗi lần yêu cầu, và service Scoped — mặc dù khả dụng — cần thận trọng vì MAUI không có khái niệm scope tích hợp như HTTP request.
Handler: Kiến trúc Đằng sau Rendering Cross-Platform
MAUI thay thế renderer của Xamarin.Forms bằng kiến trúc handler. Handler ánh xạ mỗi control cross-platform đến đối tác native thông qua một lớp trừu tượng mỏng. Điểm khác biệt chính: handler không có trạng thái (stateless) và tách biệt khỏi virtual view, giúp chúng nhanh hơn và dễ tùy chỉnh hơn.
using Microsoft.Maui.Handlers;
public class CustomEntryHandler : EntryHandler
{
protected override void ConnectHandler(MauiAppCompatEditText platformView)
{
base.ConnectHandler(platformView);
// Xóa đường gạch chân mặc định trên Android
platformView.SetBackgroundColor(Android.Graphics.Color.Transparent);
}
}
// Đăng ký trong MauiProgram.cs
builder.ConfigureMauiHandlers(handlers =>
{
handlers.AddHandler<Entry, CustomEntryHandler>();
});Trong .NET 10, các control Entry và Editor trên Android chuyển từ AppCompatEditText sang MauiAppCompatEditText, thêm hỗ trợ native cho event SelectionChanged. Các handler CollectionView và CarouselView được cải tiến từ .NET 9 giờ đã là mặc định trên iOS và Mac Catalyst, giải quyết các vấn đề ổn định tồn tại lâu.
MVVM với CommunityToolkit.Mvvm: Loại bỏ Boilerplate
Source generator CommunityToolkit.Mvvm loại bỏ khoảng 80% mã lặp MVVM. Không cần triển khai INotifyPropertyChanged thủ công, không cần command wrapper — các attribute điều khiển code generation.
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
public partial class MainViewModel : ObservableObject
{
private readonly IApiService _apiService;
public MainViewModel(IApiService apiService)
{
_apiService = apiService;
}
// Source generator tạo property 'Title' với change notification
[ObservableProperty]
private string _title = string.Empty;
// Source generator tạo async command với hỗ trợ cancellation
[RelayCommand]
private async Task LoadDataAsync(CancellationToken ct)
{
var data = await _apiService.FetchAsync(ct);
Title = data.Title;
}
}XAML binding trực tiếp đến các property và command được sinh ra:
<!-- MainPage.xaml -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:CrossPlatformDemo.ViewModels"
x:DataType="vm:MainViewModel">
<VerticalStackLayout Padding="20" Spacing="16">
<Label Text="{Binding Title}"
FontSize="24"
HorizontalOptions="Center" />
<Button Text="Load Data"
Command="{Binding LoadDataCommand}"
IsEnabled="{Binding IsLoading, Converter={StaticResource InverseBoolConverter}}" />
<ActivityIndicator IsRunning="{Binding IsLoading}"
IsVisible="{Binding IsLoading}" />
</VerticalStackLayout>
</ContentPage>Attribute x:DataType kích hoạt compiled bindings, nhanh hơn binding dựa trên reflection và tạo ra lỗi compile-time khi binding path sai.
Sẵn sàng chinh phục phỏng vấn .NET?
Luyện tập với mô phỏng tương tác, flashcards và bài kiểm tra kỹ thuật.
HybridWebView trong .NET 10: Kết nối Native và Web
HybridWebView cho phép nhúng nội dung web bên trong ứng dụng MAUI đồng thời duy trì giao tiếp hai chiều giữa C# và JavaScript. .NET 10 bổ sung ba khả năng: gọi JavaScript fire-and-forget, event khởi tạo cho cấu hình platform-specific, và chặn web request.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
// Event khởi tạo cho cấu hình platform-specific
hybridWebView.WebViewInitialized += (sender, args) =>
{
// Truy cập native platform view sau khi khởi tạo
System.Diagnostics.Debug.WriteLine("WebView ready");
};
}
// Gọi JavaScript từ C#
private async void OnCallJsClicked(object sender, EventArgs e)
{
var result = await hybridWebView.InvokeJavaScriptAsync<string>(
"getFormData", // Tên hàm JS
HybridSampleContext.Default.String // Ngữ cảnh serialization JSON
);
await DisplayAlert("Result", result, "OK");
}
// Fire-and-forget: không cần kiểu trả về (.NET 10)
private async void OnResetClicked(object sender, EventArgs e)
{
await hybridWebView.InvokeJavaScriptAsync("resetForm");
}
}JavaScript tương ứng nhận cuộc gọi và có thể gửi tin nhắn ngược lại C#:
function getFormData() {
return JSON.stringify({
name: document.getElementById('name').value,
email: document.getElementById('email').value
});
}
function resetForm() {
document.getElementById('name').value = '';
document.getElementById('email').value = '';
}Các exception JavaScript phát sinh trong InvokeJavaScriptAsync giờ đây tự động được chuyển tiếp đến .NET dưới dạng exception, loại bỏ các lỗi im lặng.
SafeAreaEdges: Layout Pixel-Perfect trên Mọi Thiết bị
.NET MAUI 10 giới thiệu property SafeAreaEdges trên Layout, ContentView, ContentPage, Border và ScrollView. Enum mới (None, SoftInput, Container, Default, All) thay thế Page.UseSafeArea cũ chỉ dành cho iOS bằng cách tiếp cận cross-platform.
<!-- Điều khiển safe area chi tiết theo từng phần -->
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
SafeAreaEdges="All">
<Grid RowDefinitions="Auto,*,Auto">
<!-- Header tuân thủ tất cả safe area -->
<Border Grid.Row="0" SafeAreaEdges="Container">
<Label Text="Header" />
</Border>
<!-- Nội dung cuộn dưới safe area -->
<ScrollView Grid.Row="1" SafeAreaEdges="SoftInput">
<VerticalStackLayout Padding="16">
<Entry Placeholder="Nhập tại đây..." />
</VerticalStackLayout>
</ScrollView>
<!-- Footer tránh home indicator -->
<Border Grid.Row="2" SafeAreaEdges="Container">
<Label Text="Footer" />
</Border>
</Grid>
</ContentPage>SoftInput điều chỉnh nội dung khi bàn phím ảo xuất hiện. Container tránh notch, vỏ cảm biến và home indicator. Các giá trị này có thể kết hợp theo từng control, cho phép header nằm dưới status bar trong khi vùng nội dung giữ nguyên.
Di chuyển từ Xamarin.Forms sang .NET MAUI
Xamarin.Forms đã kết thúc hỗ trợ vào tháng 5 năm 2024. Việc di chuyển sang MAUI bao gồm các thay đổi cấu trúc vượt xa việc thay namespace đơn thuần. Dưới đây là checklist di chuyển dựa trên kinh nghiệm chuyển đổi dự án thực tế:
Xamarin.Forms đã không còn được hỗ trợ kể từ tháng 5 năm 2024. Các ứng dụng vẫn chạy trên Xamarin có rủi ro bảo mật và tương thích. .NET MAUI 10 (LTS, hỗ trợ đến tháng 11 năm 2028) là mục tiêu di chuyển được chỉ định.
- Cấu trúc dự án — Chuyển đổi từ các dự án platform-specific sang mô hình single-project MAUI. Di chuyển mã shared về root, mã platform vào
Platforms/. - Namespace — Thay thế
Xamarin.FormsbằngMicrosoft.Maui.ControlsvàXamarin.EssentialsbằngMicrosoft.Maui.Essentials(giờ đã tích hợp trong MAUI). - Renderer sang Handler — Custom renderer phải được viết lại thành handler. API handler đơn giản hơn nhưng logic ánh xạ khác biệt.
- Startup — Thay thế khởi tạo
App.xaml.csbằngMauiProgram.cssử dụng builder pattern. - Gói NuGet — Nhiều gói thời Xamarin có tương đương MAUI. Xác minh tương thích trước khi nâng cấp.
- Dependency injection — MAUI sử dụng
Microsoft.Extensions.DependencyInjectionnative. Thay thế container DI bên thứ ba hoặc lệnh gọiDependencyService.
.NET Upgrade Assistant tự động hóa một phần bước 1-2, nhưng handler (bước 3) và điều chỉnh business logic đòi hỏi công việc thủ công.
Câu hỏi Phỏng vấn .NET MAUI Hàng đầu cho 2026
Những câu hỏi này phản ánh những gì các đội tuyển dụng hỏi trong năm 2026, dựa trên hệ sinh thái .NET 10 hiện tại.
Kiến trúc handler MAUI khác với renderer Xamarin.Forms như thế nào?
Renderer trong Xamarin.Forms có coupling chặt với cả control cross-platform và native view, tạo ra sự phụ thuộc hai chiều. Handler trong MAUI là mapper stateless: chúng nhận thông báo thay đổi property và áp dụng chúng vào native view thông qua dictionary mapper. Sự tách biệt này giúp handler dễ test, mở rộng và tái sử dụng hơn. Dictionary PropertyMapper và CommandMapper thay thế mẫu override OnElementPropertyChanged, làm cho việc tùy chỉnh trở nên tường minh thay vì ẩn trong các câu lệnh switch.
Những cạm bẫy DI lifetime nào đặc thù cho MAUI?
MAUI hỗ trợ lifetime Singleton, Transient và Scoped, nhưng Scoped hoạt động khác so với ASP.NET Core. Không có ranh giới scope tự nhiên (như HTTP request). Service Scoped được đăng ký trong MAUI hoạt động như Singleton trừ khi scope tùy chỉnh được tạo thủ công. Lỗi phổ biến: đăng ký ViewModel là Singleton khi nó giữ state đặc thù trang (dữ liệu cũ khi điều hướng), hoặc đăng ký kết nối database là Transient (cạn kiệt connection pool). Quy tắc chung: ViewModel là Transient, service là Singleton, và Scoped được tránh trừ khi lifecycle scope được quản lý tường minh.
Khi trả lời câu hỏi DI, hãy thể hiện sự hiểu biết về cách lifecycle MAUI khác với mô hình request-scoped của ASP.NET Core. Người phỏng vấn tìm kiếm nhận thức về memory leak và vấn đề state cũ đặc thù cho ứng dụng mobile chạy lâu dài.
Compiled binding khác với binding dựa trên reflection trong MAUI như thế nào?
Binding dựa trên reflection giải quyết property path tại runtime sử dụng System.Reflection, chậm và tạo lỗi runtime cho các lỗi đánh máy. Compiled binding, được kích hoạt qua x:DataType, giải quyết binding path tại compile time. Compiler sinh mã truy cập property trực tiếp, bỏ qua reflection hoàn toàn. Điều này cải thiện thời gian startup, giảm phân bổ bộ nhớ, và bắt lỗi binding khi build. Trong .NET 10, source generator XAML mới tối ưu thêm bằng cách biên dịch XAML tại build time thay vì phân tích tại runtime.
Có những chiến lược nào để chia sẻ mã giữa ứng dụng MAUI và backend ASP.NET Core?
Cách tiếp cận được khuyến nghị sử dụng shared class library chứa DTO, logic validation và business rules. Cả ứng dụng MAUI và backend ASP.NET Core đều tham chiếu library này. .NET 10 củng cố mẫu này với tích hợp .NET Aspire cho MAUI, cung cấp service discovery và telemetry xuyên suốt các dự án mobile và backend. Shared contract sử dụng source generator System.Text.Json đảm bảo tính nhất quán serialization. Ràng buộc chính: shared library phải nhắm đến net10.0 (không phải TFM platform-specific) để duy trì tính portable.
HybridWebView khác với BlazorWebView trong MAUI như thế nào?
BlazorWebView host toàn bộ ứng dụng Blazor bên trong ứng dụng MAUI. Các component Razor render vào WebView được nhúng, nhưng runtime .NET thực thi native (không qua WebAssembly). HybridWebView nhẹ hơn: nó tải nội dung HTML/CSS/JS tĩnh và cung cấp interop C#-sang-JavaScript mà không có overhead của framework Blazor. Lựa chọn phụ thuộc vào use case. BlazorWebView phù hợp cho các đội có component Blazor sẵn và muốn tái sử dụng mã. HybridWebView phù hợp cho các tình huống mà nội dung web hiện có (dashboard, bản đồ, trình soạn thảo) cần tích hợp native mà không cần framework đầy đủ.
Luyện tập thêm câu hỏi phỏng vấn .NET trên SharpSkill để củng cố các khái niệm này với bài tập tương tác.
Bắt đầu luyện tập!
Kiểm tra kiến thức với mô phỏng phỏng vấn và bài kiểm tra kỹ thuật.
Kết luận
- .NET MAUI 10 là bản phát hành LTS (hỗ trợ đến tháng 11 năm 2028) tập trung vào ổn định và hiệu năng — là lựa chọn đáng tin cậy cho ứng dụng cross-platform production
- Kiến trúc handler thay thế renderer Xamarin bằng mapper stateless, cải thiện khả năng test và tùy chỉnh thông qua
PropertyMappervàCommandMapper - Source generator CommunityToolkit.Mvvm loại bỏ hầu hết boilerplate MVVM — attribute
[ObservableProperty]và[RelayCommand]thay thế triển khaiINotifyPropertyChangedvà command thủ công - HybridWebView trong .NET 10 bổ sung gọi JavaScript fire-and-forget, event khởi tạo và chặn request cho tích hợp native-web
- SafeAreaEdges cung cấp điều khiển chi tiết cross-platform cho device cutout, bàn phím và system bar, thay thế
UseSafeAreacũ chỉ dành cho iOS - Di chuyển Xamarin.Forms đòi hỏi viết lại handler và refactoring startup — .NET Upgrade Assistant xử lý thay đổi namespace nhưng công việc thủ công vẫn cần cho custom renderer
- Chuẩn bị phỏng vấn nên tập trung vào kiến trúc handler vs. renderer, cạm bẫy DI lifetime trong ứng dụng chạy lâu, compiled binding, và đánh đổi HybridWebView vs. BlazorWebView
Bắt đầu luyện tập!
Kiểm tra kiến thức với mô phỏng phỏng vấn và bài kiểm tra kỹ thuật.
Thẻ
Chia sẻ
Bài viết liên quan

Câu Hỏi Phỏng Vấn C# và .NET: Hướng Dẫn Đầy Đủ 2026
17 câu hỏi phỏng vấn C# và .NET thường gặp nhất. LINQ, async/await, dependency injection, Entity Framework và các phương pháp tốt nhất với đáp án chi tiết.

Top 25 Câu Hỏi Phỏng Vấn ASP.NET Core: Middleware, DI và Minimal APIs
Tổng hợp 25 câu hỏi phỏng vấn ASP.NET Core về middleware pipeline, dependency injection, minimal APIs kèm giải đáp chi tiết và ví dụ code thực tế.

Entity Framework Core: Tối Ưu Hiệu Năng và Các Phương Pháp Tốt Nhất Năm 2026
Hướng dẫn toàn diện về tối ưu hiệu năng Entity Framework Core 10 trên .NET 10. Tìm hiểu AsNoTracking, compiled queries, batch updates, split queries và toán tử LeftJoin.