So far, the Kladde has two faces: the web app from K2 with Razor components, and the app from the lessons before this one with XAML pages. Both show appointments, both know about booking, but their user interfaces have nothing in common. Whoever changes the booking view changes it twice. This lesson shows how one Razor component runs in both worlds: in the browser and in the app.

As a starting picture, we assume your solution looks like this. Adjust the names to your projects and pages:

Project Contents
Kladde.Core the rules, including FreeSlots
Kladde.Web the web app with the API GET /api/slots and POST /api/bookings from K2
Kladde.Web.Client the WebAssembly island with SlotPicker, ISlotSource and HttpSlotSource from lesson 2.5.10
Kladde.App.Logic the view models with CommunityToolkit.Mvvm and their interfaces, without MAUI, with Kladde.App.Logic.Tests
Kladde.App the MAUI app: Shell, XAML pages for contacts and appointments, SQLite, an HttpClient for the API

At the end of the lesson there is a new project, Kladde.Shared. It contains the booking view as a Razor component, and both Kladde.Web and Kladde.App show the same component.

What Blazor Hybrid is

Microsoft describes Blazor Hybrid like this: the Razor components run natively on the device, in the app’s .NET process, and render to an embedded WebView control. They don’t run in the browser, and WebAssembly isn’t involved. In .NET MAUI, the control is called BlazorWebView. Because the code runs natively, the components can reach the device’s capabilities through the .NET platform.

A WebView is a piece of browser inside the app. Which one depends on the platform:

Platform WebView Source of the engine
Windows WebView2 Microsoft Edge (Chromium)
Android android.webkit.WebView Chromium, the version depends on the installed Android WebView
iOS and Mac Catalyst WKWebView Safari WebKit

From that follows what Microsoft states explicitly: the appearance of the components can differ between platforms, and you have to test it on each one. On Windows, the people who use your app also need the WebView2 runtime.

The three places where Razor components can run differ in what they’re allowed to do. The documentation on reusable components gives one example for each:

Place What works there
Blazor WebAssembly synchronous JavaScript calls
Blazor Server services that exist only on the server, such as an Entity Framework context
BlazorWebView direct access to device features, such as location services

Your shared components must not presuppose any of this. How they can still make use of the differences is explained further down.

When hybrid, when XAML

Both run in the same app, and you can mix them. You decide per screen. The following table is a trade-off, not a rule from Microsoft:

Question speaks for BlazorWebView speaks for XAML
Does the user interface already exist as a Razor component on the web? yes: reuse the same component no
Should it feel like a native control (system picker, gestures)? no yes
Is the screen at its core a form or a list that looks the same on the web? yes rarely needed
Must the appearance be exactly the same on all platforms? rather yes, with a test on each platform the controls adapt to the platform
Does the screen need a lot of device functionality (camera, sensors)? possible through interfaces, more effort closer to hand

For the Kladde, the choice goes like this: contacts and today’s appointments stay XAML, because they use the device’s database and feel like an app. The booking view already exists on the web, and it’s a form. It becomes the hybrid page.