Shared Blazor components can power UI across web and native apps, thanks to .NET MAUI.
.NET MAUI is the future of cross-platform development with .NET—a single shared code base can power native apps for mobile and desktop. And Blazor is the natural choice for modern web apps with .NET, helping developers write C# front and back.
We’ve heard the promise of .NET MAUI and Blazor together—but how realistic is it? Can Blazor developers truly power native apps with .NET MAUI while using shared components and styles? The answer is yes—let’s take a look.
.NET MAUI welcomes Blazor and other web frameworks to native land with a modern WebView. BlazorWebView is a smart UI component—an abstraction that knows how to grab the browser WebView on corresponding platforms, like iOS/Android/Windows/Mac. Developers get to render web UI on mobile/desktop apps, with the full benefit of .NET MAUI—shared cross-platform code, application lifecycle hooks and easy platform API access.
Designed natively, Progress Telerik UI for .NET MAUI and UI for Blazor can be used together for fast, friendly app development. Both offer a free trial if you are not already a user.
There are templates to get developers started using Blazor with .NET MAUI—the .NET MAUI Blazor App for Visual Studio or maui-blazor for Command Line tooling. The resulting project sets things up nicely: Pages, Shared and wwwroot—these are all artifacts known to Blazor web developers, now ready for use inside .NET MAUI apps. The MainPage hosts the WebView—and off we go with Blazor routing, components, layouts and styles.
As nice as Blazor is within .NET MAUI, the real appeal is to lure web developers to now start building cross-platform native apps. Real .NET web developers are likely already building/maintaining web apps with Blazor—it may be impractical to have them bring all Blazor assets now within a .NET MAUI app. What is much more realistic is to reuse Blazor code within native apps—while at the same time, serving the web application.
So, how do Blazor and .NET MAUI co-exist while serving their respective platforms? Simple—put them all together in a single solution and keep the common assets shared. This is not doable directly from a Visual Studio template, but totally achievable if the parts of the puzzle are broken up. Let’s look at a solution:
Here are the pieces:
The goal is to have the Blazor bits drive the existing web app as usual, but the same components/styles light up UI on mobile/desktop apps through .NET MAUI. The only way to achieve this is to keep them in a shared project—a separate Razor Class Library works perfectly. The parts of the Blazor app that actually render UI—Pages, Shared and wwwroot folders, can be conveniently moved into the Shared UI project.
The Blazor project for web and the .NET MAUI project embedding Blazor UI in native apps don’t need to have the rendering pieces—they simply need a reference to the Shared UI library, like so:
Now that the UI rendering pieces are shared between the web and native platform projects, how would they be used from Blazor across platforms?
First up, both the Blazor for web and the .NET MAUI project embedding Blazor, have the _Imports.razor file in the wwwroot folder—this is how Blazor gets all of its dependencies. The Shared UI project/namespace references need to be added here:
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using BlazorForWeb.Client
@using BlazorSharedUI
@using BlazorSharedUI.Shared
Both Blazor for web and Blazor for .NET MAUI start off with App.razor/Main.razor which loads up routing/components and the MainLayout—this is skeleton structure of the Blazor views. Since the Shared folder now houses the MainLayout outside of the Blazor for web and the .NET MAUI with Blazor projects, it needs to be pointed out explicitly to come from the Shared UI external assembly—this needs to be done for both web and native projects.
@using BlazorSharedUI.Shared
<Router AppAssembly="@typeof(App).Assembly" AdditionalAssemblies="new[] { typeof(BlazorSharedUI.Shared.MainLayout).Assembly }">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
That is all. The Blazor project for web apps continue to work as usual—just pulling UI from the Shared UI project. And the .NET MAUI project works on iOS/Android/Windows/Mac embedding Blazor UI through WebView—also pulling from the same Shared UI project. Blazor is truly everywhere now—all it takes for developers is switch which app is the Startup Project in Visual Studio.
While all the Blazor components have been moved off to a Shared UI project, both the Blazor for web and the .NET MAUI project with Blazor do maintain the starting artifact of any web-based UI—the index.html file in the wwwroot folder. This is responsible for providing structure to the HTML view, a placeholder for components and pulling in any JavaScript references. Since all the CSS for styling has been moved off to the Shared UI project, the CSS references need to be updated accordingly:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
<title>BlazorForNative</title>
<base href="/" />
<link rel="stylesheet" href="_content/BlazorSharedUI/css/bootstrap/bootstrap.min.css" />
<link rel="stylesheet" href="_content/BlazorSharedUI/css/app.css" />
<link href="BlazorForNative.styles.css" rel="stylesheet" />
</head>
<body>
<div class="status-bar-safe-area"></div>
<div id="app">Loading...</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.webview.js" autostart="false"></script>
</body>
</html>
With a shared app.css file that is used from the Shared UI library by both the Blazor for web and the .NET MAUI project with Blazor, there is now a easy way to apply styles—and have a global impact across platforms.
@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
.btn-primary {
color: #fff;
background-color: red;
border-color: #1861ac;
}
...
...
P.S. Need to follow along as you play with Blazor and .NET MAUI? Source code for the article is here.
Blazor is understandably the most exciting web framework for .NET developers—allowing C# front and back through WebAssembly. And .NET MAUI ushers in the next generation of native cross-platform development on .NET, effortlessly reaching mobile/desktop platforms from a single codebase. With a modern WebView UI component, .NET MAUI welcomes Blazor to native land—web components and styles can be rendered inside native apps on iOS/Android/Windows/Mac.
An exciting prospect for Blazor with .NET MAUI is when web developers can reuse web assets/code for reaching mobile/desktop platforms. With a little bit of shuffle of key web rendering pieces, a shared library can house all of the UI and styles—to be used for both web and native apps. Developers get to maintain web components in one spot and reuse them for Blazor apps on the web or Blazor views inside of mobile/desktop apps with .NET MAUI.
Keep reading about how .NET MAUI and Blazor work together.
Sam Basu is a technologist, author, speaker, Microsoft MVP, gadget-lover and Progress Developer Advocate for Telerik products. With a long developer background, he now spends much of his time advocating modern web/mobile/cloud development platforms on Microsoft/Telerik technology stacks. His spare times call for travel, fast cars, cricket and culinary adventures with the family. You can find him on the internet.