I've been waiting for a unified cross-platform .NET development experience and MAUI delivers, shipping as generally available in May 2022. The successor to Xamarin.Forms, MAUI unifies the Xamarin iOS and Android frameworks and adds macOS and Windows targets under a single project model.

So what's changed from Xamarin.Forms? For starters, MAUI uses a single project targeting all platforms, versus Xamarin.Forms' multi-project solution. The build output is a .NET 6+ project that targets iOS, Android, macOS, and Windows from one codebase.

The development cycle is also faster with MAUI, thanks to the hot reload in .NET 6 and the improved XAML tooling in Visual Studio 2022. The underlying rendering pipeline has been redesigned for better performance on Android, which is a big deal for Android developers.

One concrete example of this improvement: an Android app with a complex grid layout saw a 25% increase in rendering FPS after switching to MAUI’s new renderer, though we had to manually optimize image loading to avoid memory overflows on devices with less than 2GB RAM.

If you're already invested in Xamarin.Forms, you should know that support will end in May 2024. For teams with existing Xamarin.Forms applications, the migration to MAUI is recommended. The Migration Guide documents the namespace changes, project file structure changes, and renderer API changes.

I've looked at the migration process and for most applications, it's a few days of work. Complex applications with custom renderers require more effort to port to the new handler/mapper architecture, but it's doable. The Migration Guide is a big help here.

We worked with a logistics company migrating a Xamarin.Forms app with 15 custom renderers. The migration took three weeks, with two-thirds of the time spent rewriting renderers using MAUI handlers. Notably, the absence of platform-specific APIs in early MAUI versions forced us to implement workarounds like dependency services until the May 2022 GA patch resolved several gaps.

One of the coolest features in MAUI is Blazor Hybrid, which lets you embed a Blazor web application inside a MAUI native shell. The Blazor component runs in a WebView but has access to native device APIs through MAUI. This is a big deal for teams with existing Blazor web applications who want to ship a native mobile app.

Embedding Blazor in a MAUI app worked smoothly for a simple dashboard but hit a roadblock when integrating camera access. The WebView2 control on Windows required explicit permissions in the app manifest, which wasn't covered in the initial Blazor Hybrid documentation. Teams had to manually edit the generated csproj files to include these permissions, a step that caused crashes during testing until discovered in the MAUI community GitHub discussions.

So when should you use MAUI versus a web app? MAUI is the way to go when your application needs native device capabilities like camera, biometrics, push notifications, or contacts. It's also a better choice when performance requirements exceed what a web app can deliver on mobile, or when the target audience expects a native app experience.

While MAUI excels at native integration, the resulting app size can be a concern. A minimal MAUI app targeting all four platforms clocks in at ~60MB, compared to a 2MB web app. In a healthcare project, this size difference led us to adopt a hybrid approach—using MAUI for core features requiring biometrics and deferring non-critical workflows to a Progressive Web App to reduce download size on low-end devices.

On the other hand, web apps are a better fit when the feature set doesn't require native capabilities, the organisation's web expertise is stronger than its mobile expertise, or cross-platform maintenance of two codebases is not feasible. It's all about choosing the right tool for the job.