This will be a multipart series on using Blazor in different ways. I'm going to show you how you can create a Blazor WebAssembly (WASM) project and share that code across a static web app, WPF and MAUI. I'm also going to show you how you can build and deploy the static app to Azure using a yaml Azure DevOps pipeline. Additionally, I will demonstrate how you can use Azure B2C to authenticate a static web app, WPF and MAUI project to the same tenant.
In Part 1 (you are here), I'm going to outline the project and introduce Blazor.
You can find the complete code on my Blog Examples repo on GitHub .
What is Blazor?
Blazor was initial released back in 2018 as an experiment from within Microsoft. When it was first introduced, I said, “This is the future of SPA in for dotnet shops”. Look what it offers, a mostly C# experience for web developers. Of course, we have to learn the nuances of Blazor and how it works, but we benefit greatly from the experiences we already have creating C# backends. An HTML button clicks can call a C# function in a Razor component, we can use (most) standard Razor syntax just like an MVC application of yore. Blazor is now a first class citizen in dotnet land and is baked in to the framework.
If you create a new project in Rider or Visual Studio, you’ll be present with the choice between Blazor Server or Blazor WebAssembly (or WASM). We’re going to focus on the WebAssembly version today, but the main difference is that the server app will do server side rending and communicate with the client by using SignalR vs. WebAssembly that downloads the client and runs a dotnet runtime directly in the browser.
That’s both exciting and sort of terrifying at the same time. We won’t get into much of that today because I think that’s a full post on its own.
The basic web project is just Razor, CSS and an index HTML file. Any calls to a controller, API or state changes happen using JS interop where Blazor handles the communication between the front-end DOM and our C# code.
With a Blazor project in hand, we can publish the project and the output is a static website. This is basically what we’d have if we decided to use React or Angular; the main difference is that our output also contains DLLs.
We can also publish this Blazor project (or any static content) to Azure Static Web Apps, which was released for GA in 2021. This isn’t your dad’s static web apps using specially configured Azure Blob storage, this is an actual Azure service you can stand up and deploy to. I should note that the Azure DevOps task is still in preview and the CI/CD process is a bit clunky at the moment.
For this example, I copied a Bootstrap chat app template and did some tweaking to make it work for this demo. It’s not fully functional, but does allow us to log in with a user and then chat as if we were in a direct message style conversation.
Here's what our solution structure looks like.
Let's break this project structure down a bit, just so you know where the pieces are.
From the top, we have an API project. For the demo, I have a single SignalR hub for the chat. It does include an authentication mechanism for Azure B2C. I will also show how to use authorization and policies on a minimal API and compare that to a standard API controller. In the web project, I'll show how to make API calls from Blazor to these endpoints.
The B2C process for native apps is significantly different compared to the web project. I've collected and created some common components that both WPF and MAUI can share to log in a user using B2C. I've also created a token provider interface that allows the web and native projects to provide a token for the downstream API (the API project in this case). One of the interesting discoveries I found while building this out is how to "inject" (and I use "inject" loosely) a different Blazor view depending on what project is rendering the view.
Maui and WPF
Both of these projects use a hybrid approach. For Windows, they have a nearly identical process. Both reference the Shared and MSAL projects and mostly just hoist the Blazor frontend. I won't be covering the other native apps that Maui supports other than Windows.
This project is the star of the show. All three of the hosting projects (Web, Maui, WPF) reference this project and the bulk of the Blazor code lives here. I'll show you how you can set up this shared approach and how to deal with different requirements each project type might have.
This is a standalone WASM (WebAssembly) Blazor project. There are a few web-specific items to take care of, like authentication and how to get a token for our API calls. Much like the Maui and WPF, it references the Shared project for most of the Blazor work.
I'm really looking forward to diving in to this project and showing you the things I've learned. You can be on the lookout for the rest of the series. Each part of the series will focus on one of the projects and how they fit together.
As we go along, if you have any questions, please leave a comment and I will do my best to answer!