Turning a Blazor Server App into a Blazor Hybrid WPF App



Blazor Server and Blazor Hybrid can both render Razor components, but they run in very different places.

In a Blazor Server app, the UI is hosted by ASP.NET Core. The browser connects to the server over SignalR, user events travel back to the server, and the server sends UI updates back to the browser.

In a Blazor Hybrid WPF app, the UI is hosted inside a native Windows desktop application. WPF owns the window, BlazorWebView renders Razor components through WebView2, and the components run in-process with the desktop app instead of over a network circuit.

That means the main change is not rewriting your Razor UI. The main change is replacing the ASP.NET Core web host with a WPF desktop host.


1. Change the project type

A Blazor Server app usually uses the Web SDK:

<Project Sdk="Microsoft.NET.Sdk.Web">


For WPF Blazor Hybrid, the project needs Razor support plus WPF support:

<Project Sdk="Microsoft.NET.Sdk.Razor">

  <PropertyGroup>

    <OutputType>WinExe</OutputType>

    <TargetFramework>net8.0-windows</TargetFramework>

    <UseWPF>true</UseWPF>

  </PropertyGroup>

</Project>


The important changes are:

Microsoft.NET.Sdk.Razor keeps Razor component compilation available.

OutputType becomes WinExe because this is now a desktop app.

TargetFramework becomes a Windows target such as net8.0-windows.

UseWPF enables WPF build support.


2. Add the WPF BlazorWebView package

Blazor Server does not need a desktop WebView host. Blazor Hybrid does.


The WPF app uses:

<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Wpf" Version="8.0.40" />

This package provides the WPF BlazorWebView control that hosts Razor components inside a native WPF window.


3. Replace the ASP.NET Core host with a WPF application

A Blazor Server app starts from Program.cs and configures an ASP.NET Core pipeline with endpoints, static files, SignalR, and Razor components.


A WPF Blazor Hybrid app starts from App.xaml and opens a WPF window:


<Application x:Class="BlazorWPF.App"

             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

             StartupUri="MainWindow.xaml">

</Application>

There is no server endpoint to map and no browser circuit to maintain. The desktop process is the host.


4. Put BlazorWebView in the WPF window

The WPF window becomes the native shell for the Blazor UI:


<blazor:BlazorWebView HostPage="wwwroot\index.html"

                       Services="{DynamicResource services}">

    <blazor:BlazorWebView.RootComponents>

        <blazor:RootComponent Selector="#app"

                              ComponentType="{x:Type local:Main}" />

    </blazor:BlazorWebView.RootComponents>

</blazor:BlazorWebView>


This does the job that the browser normally does in a Blazor Server app:

HostPage points to the local HTML page used by WebView2.

Selector="#app" tells Blazor where to mount the component.

ComponentType="{x:Type local:Main}" selects the root Razor component.

Services provides the dependency injection container for the Blazor component tree.


5. Register Blazor Hybrid services

Blazor Server registers services with ASP.NET Core's host builder. In WPF, you create the service collection yourself:

var services = new ServiceCollection();

services.AddWpfBlazorWebView();


#if DEBUG

services.AddBlazorWebViewDeveloperTools();

#endif


Resources.Add("services", services.BuildServiceProvider());

This is the desktop equivalent of wiring up Blazor in Program.cs. Application services can be registered here too, including services that call native Windows APIs, local files, databases, or device integrations.


6. Use a local host page instead of a server-rendered page

Blazor Server commonly uses _Host.cshtml or the newer Blazor Web App hosting model. In WPF Blazor Hybrid, the host page is a static local file:


<div id="app">Loading...</div>

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

The script is different from Blazor Server. A server app uses the browser/server runtime. A hybrid app uses blazor.webview.js, which connects the Razor component runtime to the native WebView host.


7. Keep the Razor components

The best part is that simple Razor components can move across with very little change.

For example, this component works naturally inside the WPF BlazorWebView:

<h1>Hello, world!</h1>

<button @onclick="IncrementCount">

    Clicked @count times

</button>


@code {

    private int count;

    private void IncrementCount()

    {

        count++;

    }

}

The component model is still Blazor. Events, binding, dependency injection, layouts, and component composition still feel familiar. The hosting environment changed from web server to desktop window.


What changes conceptually?

Moving from Blazor Server to Blazor Hybrid WPF changes the app boundary.


In Blazor Server:

The app is a web application.

The browser is remote from the .NET process.

UI events cross a SignalR connection.

Server availability and latency matter.

Native desktop APIs are not directly available to components.

In Blazor Hybrid WPF:


The app is a Windows desktop application.

Razor components run in the same process as WPF.

UI events stay local.

Components can use desktop services through dependency injection.

WebView2 renders the UI, but WPF owns the window and application lifetime.


The short version

To make a Blazor Server app into a Blazor Hybrid WPF app, keep the Razor components, but replace the server host:

Use Microsoft.NET.Sdk.Razor instead of Microsoft.NET.Sdk.Web.

Target Windows with WPF enabled.

Add Microsoft.AspNetCore.Components.WebView.Wpf.

Create App.xaml and MainWindow.xaml.

Place BlazorWebView in the WPF window.

Register services with AddWpfBlazorWebView.

Use wwwroot/index.html with blazor.webview.js.

Mount your root Razor component into the WebView.

The result is still Blazor, but it is no longer Blazor Server. It is a native WPF desktop app with a Razor-powered UI.


[source code]

Comments

Popular posts from this blog

Customizing PWA Manifest and Icons for a Polished User Experience 🚀

Offline-First Strategy with Blazor PWAs: A Complete Guide 🚀

Yes, Blazor Server can scale!