Since .NET 6.0, the Blazor framework finds yet another path for developer success with .NET MAUI. MAUI provides a set of technologies that enable apps to run on Web, desktop, and mobile. This new pattern is named Blazor Hybrid and, once again, developers are empowered to use their existing skills to reach even more ecosystems. With Blazor Hybrid, native desktop on Android, iOS, macOS, and Windows are now within reach.

.NET MAUI stands for .NET Multi-platform App UI.

Quick recap. What is .NET MAUI?

.NET Multi-platform App UI (.NET MAUI) is a cross-platform framework for creating native mobile and desktop apps with C# and XAML. It enables cross-platform development for Android, iOS, macOS, Windows and Tizen. It is designed to create the best app experience available, just as though it was a natively designed application.


Using .NET MAUI, you can develop apps that can run on Android, iOS, macOS, and Windows from a single shared code-base.

The joy of cross-platform development is that apps look and feel like they were built for each operating system without the need for additional code. .NET MAUI uses native UI via the premier app toolkits supplied by each platform and Microsoft’s fastest mobile platform to date paired with modern developer productivity.

And... What is Blazor?

Blazor is a web framework that allows developers to build interactive web applications using C# and .NET. It eliminates the need for JavaScript and allows for server-side rendering, making it a popular choice for web development.

With Blazor, developers can use their existing knowledge of C# and .NET to create responsive and interactive web applications.

Note: For a more detailed introduction to Blazor, please read this Blazor introductory blog to get acquainted.

Blazor Hybrid applications with .NET MAUI

Blazor Hybrid support is built into the .NET Multi-platform App UI (.NET MAUI) framework. .NET MAUI includes the BlazorWebView control that permits rendering Razor components into an embedded Web View. By using .NET MAUI and Blazor together, you can reuse one set of web UI components across mobile, desktop, and web.

Note: For a more detailed introduction to .NET MAUI Blazor Hybrid, please read  this Blazor MAUI introductory Blazor Hybrid blog article to get acquainted.

What gives Assemblysoft an advantage over other software companies offering .NET MAUI developers?

Our UK and European based development team specialises in .NET, Blazor and .NET MAUI Blazor Hybrid. Simply put this means it is what we do, day in day out, for our clients and partners. We focus on delivering solutions that revolve around .NET MAUI and Blazor to ensure we remain the most skilled and knowledgeable Blazor developers you can find for your project.

Our UK and European based development team specialise in .NET, Blazor and .NET MAUI Blazor Hybrid

What are the danger signs to look out for when selecting a .NET MAUI Blazor Hybrid development partner?

Many companies will offer .NET MAUI Blazor application services because they have a history with .NET but the likelihood is that this will end up costing you valuable investment of time and money as you need to wait for them to learn Blazor and MAUI during the development of your application.

You may well end up waiting for the team to skill up with Blazor Hybrid at the cost of your budget and resources as getting it right requires extensive experience.


How well supported is .NET MAUI?

.NET MAUI is supported under the normal release schedule of 18 months and is now in line to be serviced with the monthly cadence of .NET.

The Assemblysoft advantage for .NET MAUI support

As .NET MAUI is a relatively new offering in terms of maturity, there remain a number of challenges that are not readily solved by existing libraries and documentation. As our development team at Assemblysoft have already completed a number of applications that are in production, we have already encountered and solved these challenges, saving you time and money as we leverage our deep experience.

Introducing the Blazor Hybrid Architecture

MAUI is the evolution of Xamarin.Forms, which initially targeted iOS and Android, and with MAUI, expanded into desktop. Using MAUI, you'll write cross-platform applications in a single solution with the option of writing platform-specific code as needed. Because MAUI is full-stack .NET, sharing code, logic, testing, and tooling across the solution is possible. The Blazor Hybrid pattern is built upon MAUI and implemented through the BlazorWebView, a MAUI component used to render an embedded Blazor Web view using the WebView2 runtime.

.NET MAUI uses a single API to unify Android, iOS, macOS, and Windows APIs into a write-once run-anywhere developer experience. MAUI apps provide deep access into each native platform. .NET 6 introduces a series of platform-specific frameworks: .NET for Android, .NET for iOS, .NET for macOS, and Windows UI (WinUI) Library. The .NET 6 Base Class Library is shared among all the platforms while abstracting the individual characteristics of each platform from your code. The .NET runtime is used for the execution environment for MAUI applications, even though the underlying implementations of the runtime may be different, depending on the host. For example, on Android, iOS, and macOS, the environment is impended by Mono (a .NET runtime), and on Windows, WinRT provides the environment with optimizations for the Windows platform.

In a .NET MAUI app, you write code that primarily interacts with the .NET MAUI API, shown in Figure 4 (1). .NET MAUI then directly consumes the native platform APIs, as in Figure 4 (3). In addition, app code may directly exercise platform APIs, shown in Figure 4 (2), if required.

Figure       4      : A block diagram of the MAUI platform

MAUI is more than an abstract BCL to share common business logic on different platforms - it also unifies user interface (UI) development too. .NET MAUI provides a single framework for building the UIs for mobile and desktop apps. Because each platform has their own models and elements used to describe their UI, using individual platform-specific frameworks would be difficult to maintain. Instead, MAUI provides a common multi-platform framework for creating user interfaces, while having the flexibility to target specific platforms as needed. In addition to native UI frameworks, MAUI also introduces the BlazorWebView. Through a BlazorWebView component, MAUI apps can use the Blazor Web framework creating a .NET MAUI Blazor application.

BlazorWebView and .NET MAUI Blazor

The Blazor Hybrid pattern uses a BlazorWebView component that enables Blazor within a MAUI application, creating a .NET MAUI Blazor application. .NET MAUI Blazor enables both native and Web UI in a single application and they can co-exist in a single view. With .NET MAUI Blazor, applications can leverage Blazor's component model (Razor Components), which uses HTML, CSS, and the Razor syntax. The Blazor part of an app can reuse components, layouts, and styles that are used in an existing regular Web app. BlazorWebView can be composed alongside native elements; additionally, they leverage platform features and share state with their native counterparts.

In .NET MAUI Blazor apps, all code, both for the native UI parts and the Web UI parts, runs as .NET code on the platform's runtime using a single process. There's no local or remote Web server and no WebAssembly (WASM) in the Blazor Hybrid pattern. The native UI components run as the device's standard UI components (button, label, etc.) and the Web UI components are hosted in a Web view. The components can share state using standard .NET patterns, such as event handlers, dependency injection, or anything else you're already using in your apps today.

Creating a .NET MAUI Blazor Application

Creating your first .NET MAUI Blazor Application is familiar, yet new, territory for most developers. Although .NET technologies like Xamarin.Forms and Blazor have been around for some time, using them together is a new experience. The best way to ensure success is to install the latest updates for all the technologies involved. Thankfully, there are installers for the required SDKs and the version of Visual Studio 2022 with support for MAUI is just a few clicks away. Once the prerequisites are installed, I'll look at the .NET MAUI Blazor template and get an understanding of how the project is structured. Let's install everything now.

The examples provided are just one approach to using the BlazorWebView with MAUI. In this scenario, Blazor is used exclusively within the application shell providing the complete UI and navigation by the Main component, which is specified in the ComponentType parameter. Overtaking the entire app with a BlazorWebView component is optional; it can be added ad hoc to any XAML view and even mixed with native UI components. Mixed UIs can share application state and fully interact, as shown in Figure 11.

Figure       11      : A .NET MAUI Blazor app with mixed Native and Web UI using a shared state.

Hybrid Ecosystem

.NET 6 will further strengthen the developer ecosystem that surrounds MAUI and Blazor. Since the very beginning when Blazor was just an experiment, libraries supporting the app model started springing up. The same excitement can be seen with MAUI as well. Telerik, a brand synonymous with .NET developers for nearly 20 years, has already announced Telerik UI for MAUI (https://www.telerik.com/maui-ui). Telerik has a dedicated MAUI solution and a dedicated Blazor UI offering with 85+ components, embracing a future where developers have the choice of using platform-native UIs with MAUI and XAML, Blazor with HTML, or both UI component libraries working together seamlessly. The key takeaway here is that developers have choices as to how to implement UI that is unprecedented in .NET development.

As the Blazor ecosystem continues to grow and flourish, it will be further enhanced with packages enabled by MAUI via native platform integration and runtime execution. Libraries that may have been hampered by incompatibilities prior to MAUI find a new niche with Blazor Hybrid. For example, ML.NET, an open source, cross-platform machine learning (ML) framework for .NET devs, has seen limitations around WebAssembly. With Blazor Hybrid, the compatibility problem becomes less relevant as ML.NET and MAUI push to cover the same execution environments (https://devblogs.microsoft.com/dotnet/ml-net-june-updates-model-builder/#ml-net-release).

Expectations are high here as developer options increase due to the expanding reach of MAUI and Blazor Hybrid, while new libraries and frameworks emerge to provide new and unique solutions.

Migration Paths

If the Blazor Hybrid pattern using .NET MAUI Blazor seems interesting but you're currently developing for WPF or Windows Forms, then hybrid feels out of reach. Traditionally, migrating an existing app to a new platform requires a lot of manually rewriting code, but the .NET team has provided a transitional pathway. In .NET 6, a BlazorWebView component was added to both WPF and Windows Forms. This means that existing projects using .NET can be upgraded to .NET 6.0, and, with a few steps, enable BlazorWebView.

By enabling BlazorWebView in WPF and Windows Forms, it's possible to start decoupling UI investments from WPF and Windows Forms. These Blazor-enabled projects only target the Windows platform, unlike MAUI. This is a great way to modernize existing desktop apps in a way that can be brought forward onto .NET MAUI or used on the Web. By using Blazor to modernize existing Windows Forms and WPF apps, existing investments can be leveraged with a transitional Blazor Hybrid application.

To use the new BlazorWebView controls, you first need to make sure that you have WebView2 runtime installed. This is the same WebView2 runtime used by Blazor Hybrid for .NET MAUI Blazor.

The following requirements must be met to add Blazor functionality to an existing Windows Forms app:

  • Update the Windows Forms app to target .NET 6.
  • Update the SDK used in the app's project (csproj) file to Microsoft.NET.Sdk.Razor.
  • Add a package reference to Microsoft.AspNetCore.Components.WebView.WindowsForms.
  • Add the wwwroot/index.html file from Listing 3 to the project, replacing {PROJECT NAME} with the actual project name.
  • Add the app.css file from Listing 4, with some basic styles to the wwwroot folder.
  • For all files in the wwwroot folder, set the Copy to Output Directory property to Copy if newer.
  • Add a root Blazor component Counter.razor from Listing 5 to the project.
  • Add a BlazorWebView control in Listing 6 to the desired form to render the root Blazor component.
  • Run the app to see your BlazorWebView in action, shown in Figure 12.

Listing 3: Index.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,
        initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>Blazor app</title>
    <base href="/" />
    <link href="{PROJECT NAME}.styles.css" rel="stylesheet" />
    <link href="app.css" rel="stylesheet" />
</head>

<body>
    <div id="app"></div>

    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss">X</a>
    </div>

    <script src="_framework/blazor.webview.js"></script>
</body>
</html>

Listing 4: app.css

html, body {font-family: 'Helvetica Neue', 
               Helvetica, Arial, sans-serif;}

.valid.modified:not([type=checkbox]) {outline: 1px solid #26b050;}

.invalid {outline: 1px solid red;}

.validation-message {color: red;}

#blazor-error-ui {
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}

Listing 5: Counter.razor

@using Microsoft.AspNetCore.Components.Web

<h1>Counter</h1>

<p>The current count is: @currentCount</p>
<button @onclick="IncrementCount">Count</button>

@code {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount++;
    }
}

Listing 6: MyForm.cs

var serviceCollection = new ServiceCollection();
serviceCollection.AddBlazorWebView();
var blazor = new BlazorWebView()
{
    Dock = DockStyle.Fill,
    HostPage = "wwwroot/index.html",
    Services = serviceCollection.BuildServiceProvider(),
};
blazor.RootComponents.Add<Counter>("#app");
Controls.Add(blazor);
Figure       12      : A Blazor Hybrid enabled WinForms application

To add Blazor functionality to an existing WPF app, follow the same steps listed above for Windows Forms apps, except:

  • Substitute a package reference for Microsoft.AspNetCore.Components.WebView.Wpf
  • Add the BlazorWebView control in XAML, as shown in Listing 7.
  • Set up the service provider as a static resource in the XAML code-behind file (such as MainWindow.xaml.cs), as shown in Listing 8.
  • To satisfy tooling requirements for the WPF runtime, add an empty partial class from Listing 9 for the component in Counter.razor.cs.
  • Build and run your Blazor based WPF app, shown in Figure 13.

Listing 7: MainWindow.xaml


<Window x:Class="WpfApp1.MainWindow"
        xmlns="..."
        xmlns:local="clr-namespace:WpfApp1"
        xmlns:blazor="clr-namespace:Microsoft.AspNetCore.Components.WebView.Wpf;
        assembly=Microsoft.AspNetCore.Components.WebView.Wpf"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <blazor:BlazorWebView HostPage="wwwroot/index.html"
                              Services="{StaticResource services}">
            <blazor:BlazorWebView.RootComponents>
                <blazor:RootComponent Selector="#app"
                                      ComponentType="{x:Type local:Counter}" />
            </blazor:BlazorWebView.RootComponents>
        </blazor:BlazorWebView>
    </Grid>
</Window>

Listing 8: MainWindow.xaml.cs

var serviceCollection = new ServiceCollection();
serviceCollection.AddBlazorWebView();
Resources.Add("services", serviceCollection.BuildServiceProvider());

Listing 9: Counter.razor.cs

public partial class Counter { }
Figure       13      : A Blazor Hybrid-enabled WPF application

What to Expect Next

The Blazor Hybrid pattern and .NET MAUI Blazor marks a huge milestone for .NET 6 and the work doesn't end there. .NET 7 is expected in November 2022 and with it, even more Blazor is anticipated. Another Blazor experiment, Blazor Mobile Bindings, is likely to ship in the .NET 7 release. Blazor Mobile Bindings is extension of the Xamarin > MAUI evolution that uses Razor syntax to define UI components and behaviors. By enabling the Razor syntax as a replacement for XAML, context switching becomes almost trivial. In .NET 7 with Blazor Mobile Bindings, .NET MAUI Blazor apps will have nearly identical coding patterns whether it's a native view (XML and Razor) or Web-based view (HTML and Razor). In Listing 10, a Counter component is composed of XML using the Razor syntax to create a native UI. The Counter component looks very similar to the HTML-based Web component, except for platform-native StackLayout, Label, and Button components defined in XML.

Listing 10: Counter.razor (XML)

<StackLayout>
    <Label FontSize="30"
           Text="@("You pressed " + count + " times")" />
     <Button Text="+1"
             OnClick="@HandleClick" />
</StackLayout>

@code {
    int count;

    void HandleClick()
    {
        count++;
    }
}

Just as .NET MAUI Blazor apps using XAML, application UI logic can be mixed using the BlazorWebView component. With the Razor, the experience is even more seamless as Razor directives and code blocks can be used and follow the same conventions as HTML-based components. In Listing 11, a hybrid view uses both native UI and BlazorWebView to display a counter while sharing app state among all components. The @inject directive is safe to use in the context of Blazor Mobile Bindings and provides dependency injection for native components just as it does for Web components. The similarities continue with Razor data binding on the Label and Button components. The Web component code, which will be rendered by the BlazorWebView, looks very similar regarding syntax, as shown in Listing 12.

Listing 11: Main.razor

@inject CounterState CounterState

<ContentView>
    <StackLayout>

        <StackLayout Margin="new Thickness(20)">
            <Label Text="@($"You pressed {CounterState.CurrentCount} times") 
                "FontSize="30" />
            <Button Text="Increment from native" 
                OnClick="@CounterState.IncrementCount" Padding="10" />
        </StackLayout>

        <BlazorWebView ContentRoot="WebUI/wwwroot"
                        VerticalOptions="LayoutOptions.FillAndExpand">

            <FirstBlazorHybridApp.WebUI.App />
        </BlazorWebView>

    </StackLayout>
</ContentView>

@code {
    // initialization code
}

Listing 12: App.razor

@inject CounterState CounterState

<div style="text-align: center; background-color: lightblue;">
    <div>
        <span style="font-size: 30px; font-weight: bold;">
            You pressed @CounterState.CurrentCount times
        </span>
    </div>
    <div>
        <button style="margin: 20px;" @onclick="ClickMe">
             Increment from HTML
         </button>
     </div>
</div>

@code
{
    private void ClickMe()
    {
        CounterState.IncrementCount();
    }

    // initialization code
}

Blazor Mobile Bindings looks promising. It continues to blur the boundaries between native and Web programming, further extending the usefulness of existing .NET skills. Blazor has found an audience with Web developers by offering a solution to a .NET audience where JavaScript was the only player. Blazor Hybrid and MAUI carry that same tradition with cross-platform native app development via Blazor Mobile Bindings.

A New Era of Blazor Productivity, Again

When .NET 3.0 was released, it included Blazor for the first time. At the time, I wrote an article entitled A New Era of Blazor Productivity . The sentiment I expressed there holds true again: “As powerful as it is convenient, Blazor makes a great choice for new applications. By combining .NET technologies that you're already using with an intuitive component model, Blazor has created a new era of productivity.”

With the Blazor Hybrid pattern, .NET and related tools shorten the learning curve and makes cross-platform development approachable. When using a Blazor Hybrid pattern, the tradeoffs with WebAssembly are reduced. Xamarin evolves to MAUI and brings native APIs to Android, iOS, macOS, and Windows, while BlazorWebViews enable Web architecture. As Blazor grows, the community and ecosystem will continue to grow with solutions for common problems. Blazor's roadmap shows commitment and promise that Blazor is here to stay by delivering innovative technologies to help you build modern applications.

WebView2

The Microsoft Edge WebView2 control allows embedded Web technologies (HTML, CSS, and JavaScript) in native apps. The WebView2 control uses Microsoft Edge (Chromium) as the rendering engine to display the Web content in native apps.

With WebView2, Web code can be embedded in different parts of your native app, or a single WebView instance can be used to wrap the entirety of the app.

Distributing WebView2 with an application can be resolved in two ways. An “Evergreen distribution” approach can be used, which relies on an up-to-date version of Chromium with regular platform updates and security patches. Alternatively, a “Fixed Version” distribution can be used by packaging a specific version of the Chromium bits in the app.

WebView2 is supported by a wide range of Windows versions from 7 and up, and serves as a vehicle for migrating legacy applications. Through WebView2, an app can be transitioned from an existing technology to Web components using a piece-by-piece strategy.

Conclusion

.NET MAUI’s key advantage is the mature, sophisticated, and widely available .NET ecosystem that provides great interoperability and code re-usability, high quality and well-supported libraries, powerful tools and IDEs, and a large active community of developers. Depending on what your business needs are, choosing the .NET stack is often a preferred option, especially for enterprise development, because of the stability, open-source, re-usability, support and longevity that it offers.

Our experience has been great and our developers absolutely love working with .NET MAUI. We would be happy to share our experiences with you, having now completed the development of a number of commercial, cross-platform applications using .NET MAUI targeting: IOS | Android | Windows. We are actively developing a number of Blazor Hybrid (.NET MAUI Blazor applications) from our Bournemouth based development agency in the United Kingdom.

Assemblysoft are a .NET Agency with a focus on .NET MAUI and Blazor

dotnet-bot-maui-cross-platform-development