- Lab
-
Libraries: If you want this lab, consider one of these libraries.
- Core Tech
Guided: Exploring Blazor's Hosting Models
.NET 8 has ushered in an array of exciting new features, notably enhancing Blazor hosting capabilities. This lab offers a hands-on experience with configuring a versatile .NET 8 Blazor application. You'll learn to seamlessly integrate Blazor Server, Blazor WebAssembly, and the innovative Blazor Server-Side Rendered components into a unified application.
Lab Info
Table of Contents
-
Challenge
1. Introduction
Welcome to the lab:
Guided: Exploring Blazor's Hosting Models.
What's New in .NET 8
Since 2019, ASP.NET's Blazor has enabled C# developers to extend their expertise to front-end development in web-based applications.
With the launch of .NET 8, Blazor introduced a third rendering mode known as Server-Side Rendering (SSR). This option fully processes the component on the server, rendering it to HTML, and sending just that HTML back to the client.
Additionally, Blazor now allows for the rendering mode to be declared at the component-level, rather than globally for the entire project.
This significant advancement enables individual components to select the most suitable hosting model for their specific requirements.
Options include: Blazor Server for robust client interactions, Blazor WebAssembly for complete client-side execution, and the new SSR for improved performance and enhanced SEO.
What to Expect
In the upcoming steps, you'll learn how to configure a simple Todo component to operate under each of these rendering modes.
You'll see firsthand how each mode offers unique benefits and trade-offs to developing your components.
No Prior Knowledge This lab is designed with the assumption that you have a basic understanding of Blazor. Therefore, some implementation details may not be explored in depth.
If you are new to Blazor or Razor syntax, you are encouraged to proceed. You can be confident that all of the major points will be addressed thoroughly.
To continue the lab, click the right arrow.
If you are interested, following is an expanded history of Blazor's evolution.
📰 Blazor's History
**** ### Blazor ServerLaunched in 2019 with ASP.Net Core 3.0, Blazor Server emerged as a pivotal development for .NET enthusiasts. It shifted the paradigm of web application development from a JavaScript-centric approach to leveraging C# capabilities.
This was accomplished by utilizing a persistent SignalR connection, enabling seamless communication between the browser and the server. User interactions are processed server-side in C#, with updates dynamically reflected on the client's browser, illustrating real-time web functionality
Blazor WebAssembly
The subsequent year ASP.NET Core introduced Blazor WebAssembly. This innovation transformed the landscape of web development by allowing entire applications to be hosted entirely in the client's browser.
Written in C# and compiled into WebAssembly, this approach empowered the execution of .NET code directly in the browser, freeing it from server-side dependencies. This breakthrough provided a robust alternative to traditional JavaScript frameworks, enabling developers to construct rich, interactive UIs entirely in C#.
Blazor Server-Side Rendering (SSR)
With .NET 8's release, a novel rendering mode, Blazor Server-Side Rendering (SSR), was introduced. This mode involves server-side component rendering into HTML, akin to Razor Pages or MVC, but with the added advantage of Blazor's component-based architecture. Key features like Stream Rendering and Enhanced Navigation further augment this mode's capabilities.
Component Level Rendering
A significant advancement in .NET 8 is the component level declaration of different rendering modes within a single project. This flexibility contrasts with earlier versions, where a singular hosting model was a project-wide commitment.
For example, straightforward pages like
AboutorHomecan be efficiently rendered server-side, while complex, interactive elements can coexist on more dynamic pages. This approach offers a strategic solution to the complexities previously associated with client interactivity in web applications. -
Challenge
2. Getting Started
Overview
Before getting started, take a moment to get familiar with the lab's interface.
ℹ️ Lab Environment
**** #### Explorer Tab The filesystem is accessible using the **Explorer** tab identified with the stacked paper icon at the top left. You can open this tab whenever you need to interact with the project files.Source Control
This lab utilizes source control to assist you in navigating changes to files.
Should you encounter any difficulties with a specific step, you can access guidance through the Source Control tab on the left, which is marked with a branch icon.
Within the main branch, you'll find the final state of each file. This allows you to either open the changed file to view the necessary changes or simply use the back arrow to revert the file to its final state.
⏯️ Running the Project
To start running the project, click on the `watch` task link. This command will start the project and will also automatically rebuild the project whenever you make changes. > If you ever see an error message in the **Terminal** window, you can always just click the **watch** link again to restart the project.Once the project is running, you can click to open the application in a new browser window:
Open Application: {{localhost:5200}}
.NET's hot reload feature is currently turned off, you will need to manually refresh the browser window to see your changes.
Application Overview
Once you have refreshed the browser, you will find several tabs on the left side, which will be used to link to the various versions of this component.
Note that depending on the browser window's width, you may need to first click on the three line icon in the upper right corner.
For now, click on the Todo - SSR tab to see the basic layout of the todo component.
Take a moment to notice the key features of the component, and some missing functionality:
1️⃣ Undone Todo Count
**** The count to the right of the **Todo (1)** header indicates the number of tasks that are not marked as complete.2️⃣ Todo Entry
**** In the **Something todo** entry field, feel free to enter a task and click **Submit**.If you try to add a second time, you'll notice that your previous entry is replaced by the new one.
3️⃣ Checkbox Completion
**** Try clicking the checkbox next to any item to mark it as completed. Observe that the undone count does not update when you do this.In the upcoming steps, each of these areas will be addressed, providing insights into the trade-offs to consider when choosing a particular rendering mode.
Click the right arrow to begin configuring the Server-Side Rendering version of the Todo component.
-
Challenge
3. Overview of an SSR Component
Overview of an SSR Component
Static Server-Side Rendering (SSR) fully renders the logic of a
.razorcomponent on the server and sends the static HTML back to the client.🔀 SSR Trade-offs
**** With the release of .NET 8, **Static Server-Side Rendering (SSR)** has been established as the default rendering mode.Unless configured otherwise, a
.razorfile will be rendered using SSR, with the resulting static HTML sent to the client.This introduces a trade-off of:
No Client Interactivity
Consequently, once the page reaches the client, it can no longer interact directly with the application's C# logic, a distinguishing feature of Blazor, until now.
But, No Overhead and SEO Friendly
On the other hand, this approach reduces the overhead typically associated with other rendering modes, thereby enhancing performance. Additionally, the use of plain HTML is beneficial for optimizing SEO.
For example, this method eliminates the need for the continuous SignalR connection that Blazor Server requires and bypasses the necessity to download WebAssembly packages, as is the case with Blazor WebAssembly.
Code Review
To explore how this SSR component is configured: Open the
TodoSSR.razorfile. Identify where the three main elements mentioned earlier are defined.*️⃣ Undone Todo Count
**** Starting with the count of undone tasks, which can be seen within the `` tag, you'll encounter the first trade-off of using the **SSR** rendering mode.
Notice the inline Razor expression used to retrieve the number of undone
TodoItems in thetodoslist.While this expression effectively populates the count of current todo items during rendering, it won't update in real-time on the client side. Instead it will only change upon the next page refresh, such as when you create a new todo item.
*️⃣ Todo Entry Form
**** Next, consider the `` component. This component serves as a convenient tool for constructing an HTML form and seamlessly integrating it with your component's logic.
However, the page is still rendered as a basic HTML form on the client-side, which needs to submit changes back to the server, similar to a traditional request/response model.
This process currently results in a full page refresh. Though you will soon discover some convenient functionality that Blazor has developed to mitigate this.
*️⃣ List of Tasks
**** Immediately following the `` is a Razor conditional statement that reacts to the current status of the `todos` collection. Displaying whether there are any todo items or not. Though you may be wondering about the first Loading message. If SSR always returns static HTML, you might be curious when the Loading text would appear to the client.
The answer lies in a key feature of Blazor SSR called stream rendering, which will be addressed in the next step.
To continue learning more about SSR's stream rendering, click on the right arrow.
-
Challenge
4. Configuring SSR's Stream Rendering
Stream Rendering
Traditional web-based applications often face common issues such as: slow response times for longer processes, the need for page refreshes during client interactions, and challenges like maintaining client scroll positions.
While SSR primarily renders static HTML pages, stream rendering has been introduced to offer a more dynamic user experience.
The following steps will guide you through implementing these features.
🔎 Provided Configurations
**** Before digging into any configurations you will need to make, you may be interested in seeing what configurations have already been provided for you.Program.cs Configuration
To see how an SSR project has been configured you can:
Open the Program.cs file. Specifically look for the following two lines:
builder.Services.AddRazorComponents(); . . . app.MapRazorComponents<App>();These two lines form the foundational configuration for an ASP.Net Blazor project, which by default includes support for Server-Side Rendering (SSR).
In the subsequent steps of this lab, you will add to this configuration to incorporate functionality for the other hosting models.
Blazor Javascript Framework
In addition to the server configurations, Blazor also includes the
blazor.web.jsjavascript framework.This framework helps to capture client side requests and process them through the configured hosting model.
You can see the inclusion of this script file in the App.razor file.
<script src="_framework/blazor.web.js"></script>Now, for the configurations you'll need to add to the todo component to support stream rendering:
1️⃣ Add the Stream Rendering Attribute
**** To enable SSR's stream rendering functionality, simply add an attribute towards the top of the **TodoSSR.razor** fileJust under the
@page "/todossr"directive, insert the attribute:@page "/todossr" @attribute [StreamRendering]Now, when you refresh the Todo - SSR page, you will initially see the Loading message and an empty Todo () count. Following the simulated delay, the page will update to display the final state.
Speed up Testing In order to demonstrate this Loading message the
Task.Delay()has been set to 2 seconds, feel free to lower this value if you would like to speed up your testing.2️⃣ Enhanced Navigation
**** In addition to the temporary state, the **StreamRendering** attribute also offers **Enhanced** navigation functionality.This feature helps to mitigate some page refreshes and the loss of client scroll position, such as when posting a new todo item.
Demonstrate the Issue
To demonstrate this, you can push the todo entry form down the page, forcing you to scroll to this position.
This can be achieved by inserting the following
<div>above the<EditForm>component, adding a significant height:<div style="height:100vh" /> <EditForm . . .After making this change, refresh the Todo - SSR page, scroll down to the todo entry form, create a new item, and then click Submit.
You'll notice that the page refreshes and brings you back to the top of the page.
Enhancing the User Interface
With stream rendering enabled, you can prevent a full page refresh by adding the
Enhanceattribute to theEditFormcomponent:<EditForm Enhance . . .After refreshing the Todo - SSR page, try adding another todo item. You'll notice that the item is added without the page flash or altering your position on the page.
How does this work?
In the SSR hosting model, although page requests adhere to the traditional request/response format, the
blazor.web.jsframework plays a critical role. It intercepts these requests, processes them in the background, and integrates any updates into the existing page.This approach significantly improves the user's experience despite that SSR pages are not as fully interactive as the other rendering modes.
3️⃣ Interactivity Limitations
**** Enhanced stream rendering has significantly improved the user experience compared to plain HTML. However, there are still some functionality issues with the current component. For example, newly added items overwrite the previously added ones, and the **TODO ()** count does not dynamically update as items are checked off as complete.These issues could be addressed with additional logic. At this stage, it’s crucial to weigh the trade-offs: deciding whether to continue refining the SSR component to suit current requirements or to switch to another hosting model, like Blazor Server, to take advantage of its features.
Feel free to take a moment to consider how you might optimize the current SSR component to meet the requirements.
The transition to the Blazor Server rendering mode will be explored in the next step, whenever you're ready to proceed.
Click on the right arrow to explore how to configure a component for the Blazor Server rendering mode.
-
Challenge
5. Configuring Blazor Server
Configuring the Blazor Server
Blazor Server, the original hosting model, enables direct interaction between the client and the server-hosted C# logic. This is interaction is facilitated through a persistent SignalR connection with the server.
🔀 Blazor Server Trade-offs
**** #### Open SignalR ConnectionThe main trade-off to consider when choosing the Blazor Server rendering mode is the need for the server to maintain an open SignalR connection for every client accessing your application.
But, Enhanced Client Experience
However, the enhancements to client interactivity provided by this model may well justify this trade-off.
🗒️ Component-level Rendering
**** With the introduction of component-level rendering declarations, you have the flexibility to decide which components use this resource-intensive model.A resource intensive Blazor Server component can be separated from other components that can easily be rendered through SSR
While server resource considerations remain important, their impact can be moderated based on the anticipated usage of the individual components, rather than the entire application.
1️⃣ Configuring the Project
**** To begin using **Blazor Server**, the project needs to be configured to use the interactive server.This can be accomplished by adding options to the two configurations previously seen in the
Program.csfile of the BlazorHosting project.Add the interactive server components to the available services towards the top of the Program.cs file
That line should now look like:
builder.Services.AddRazorComponents() .AddInteractiveServerComponents();Then towards the bottom of the file, add the interactive server render mode to the project.
app.MapRazorComponents<App>() .AddInteractiveServerRenderMode();New Blazor Template
With this new releases, .NET 8 has also introduced a new project template for
blazor.Among the flags for this template is also the
-int, --interactivityflag. This option allows you to declare what rendering modes will be supported by your project.Passing in the flag
-int Serverwill automatically make the above configurations for you.The other
-intoptions are:
None- Supports only SSR
Server- Supports SSR and Blazor Server
WebAssembly- Supports SSR and WebAssembly
Auto- Supports all rendering modes2️⃣ Configuring the Component
**** Now that the project is configured to use **Blazor Server**, you can begin configuring your page components to utilize this rendering mode.Add the following line, at the top of the TodoServer.razor file just under the
@page "/TodoServer"directive.@page "/TodoServer" @rendermode InteractiveServerReview Changes
Navigate to the Todo - Server page and experiment by adding several todo items and checking some as done. You'll notice the page now functions as expected.
This level of functionality is enabled by the persistent SignalR connection. This connection retains the client's state on the server allowing for dynamic interaction with all page elements, but not limited to just the inputs within a form.
Take a moment to compare the differences between these two
razorpages. Pay special attention to how the Blazor Server pages interact with<input>elements, regardless of whether they are placed inside forms.Feel free to experiment with this Blazor Server render mode. You might also try adding the
@rendermode InteractiveServerattribute to the top of the Todo - SSR page. This will demonstrate how easily the rendering mode can be changed for any page.When you're prepared to explore the Blazor WebAssembly hosting model, click the right arrow to proceed.
-
Challenge
6. Configuring Blazor WebAssembly
Configuring Blazor WebAssembly
Blazor WebAssembly represents another rendering mode that allows an interactive client application to be developed using C#.
Contrasting with Blazor Server, which relies on an active SignalR connection, Blazor WebAssembly compiles the C# logic into a WebAssembly package. This package is then installed and ran directly within the client's browser.
🔀 WebAssembly Trade-offs
**** When considering **Blazor WebAssembly**, it's important to be aware of its trade-offs:Delay Waiting to Download
Before the application can run in the client's browser, the entire package — which includes all client application logic and supporting frameworks — needs to be downloaded to the client's browser. The file size, influenced by the application's complexity, can be significant. This might lead to a delay before the user is able to see any content.
But, No Active Connection
Despite this possible delay, a notable advantage is that, once the application is loaded into the browser, there is no need for the client to maintain a constant connection to the server.
Though, No Direct Connection
Though this also means that it does not have direct interaction with the server-side logic. All interactions with the server must therefore be managed through API calls. This aspect necessitates careful architectural planning for the application.
1️⃣ Creating the Client Project
**** When adopting the WebAssembly rendering mode, creating a separate client project is essential. This project will encapsulate all the application logic destined for the client's browser, ensuring that the WebAssembly package contains only what is necessary.Opening the Explorer tab, you will find that this solution already includes a BlazorHosting.Client project. Within this project, the
TodoWasm.razorfile is provided containing logic similar to what you've been working with so far.2️⃣ Referencing the Client Project
**** Before the **BlazorHosting** project can serve components declared in the **BlazorHosting.Client** project, it needs to be properly configured to recognize the client project.This involves not only adding the client project as a reference but also referencing the client project's assembly in the BlazorHosting's
Program.csfile.At the bottom of the Program.cs file, right after adding the interactive server render mode, include a reference to the client project assembly as follows:
app.MapRazorComponents<App>() .AddInteractiveServerRenderMode() .AddAdditionalAssemblies(typeof(TodoWasm).Assembly);Expectations
With just this configuration, any
.razorpages declared in the client project can be rendered using SSR.There are a couple more configurations required to be able to support Blazor WebAssembly
3️⃣ Configuring the Project
**** Similar to **Blazor Server**, **Blazor WebAssembly** also requires configuration within the `Program.cs` file of the **BlazorHosting** project.At the beginning of the
Program.csfile, incorporate the interactive WebAssembly components into the available services with the following code:builder.Services.AddRazorComponents() .AddInteractiveServerComponents() .AddInteractiveWebAssemblyComponents();Then, towards the end of the file, include the interactive WebAssembly render mode. This should be added in conjunction with the additional assemblies that you've previously specified:
app.MapRazorComponents<App>() .AddInteractiveServerRenderMode() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(TodoWasm).Assembly);Multi Rendering Mode Support In this example, all three hosting models - SSR, Blazor Server, and Blazor WebAssembly - are configured for use in this application.
Alternatively, you have the option support SSR in conjunction with either Blazor Server or Blazor WebAssembly. Remember, SSR is always available as the default option.
4️⃣ Configuring the Component
**** Now that the project is configured for WebAssembly rendering, you can start configuring your components to take advantage of this rendering mode.Open the TodoWasm.razor file, then locate the
@page "/todowasm"directive. Just below that line, add the following rendermode attribute@page "/todowasm" @rendermode InteractiveWebAssembly🔎 Review the Page
**** Navigate to the **Todo - WebAssembly** page and experiment by adding several todo items and checking some as done. You'll notice the page functions just like the **Blazor Server** version, though all logic is running within the browser.Pre-Rendering
You may notice a slight change in the interface, particularly the addition of a Render Mode indicator at the top of the page.
When you refresh the page, you will see that this briefly states Server Rendered before switching to WASM Rendered.
This behavior is a result of page pre-rendering, a process that will be explained further.
🔎 Pre-Rendering Considerations
**** As demonstrated by a page refresh, there seems to be an intermediate stage where the WebAssembly page briefly retrieves information from the server before fully transitioning to the WebAssembly package.Upon reviewing the
TodoWasm.razorfile, you will find a reference to theISharedService. Further examination of theProgram.csfiles in both the BlazorHosting and BlazorHosting.Client projects reveals that each project injects its own version of this service.BlazorHosting/Services/ServerService.csandBlazorHosting.Client/Services/WASMService.csfor their respective projects.Initially, when the page is requested, the server provides a pre-rendered (non-interactive) page to quickly display something to the user. Following this, the actual WebAssembly application takes over.
This behavior was also present in Blazer Server, though it was less apparent in that context.
If the initial pre-rendering stage is not desired, you can suppress it by modifying the
@rendermodeattribute in theTodoWasm.razorfile as follows:@rendermode @(new InteractiveWebAssemblyRenderMode(false))With this modification, when you refresh the page, the intermediate pre-rendering stage is bypassed, allowing only the WebAssembly application to respond directly to the client.
Click on the right arrow to learn about the fourth rendering mode.
-
Challenge
7. Interactive Auto Rendering
Interactive Auto Rendering
You may have observed that there is one more
@rendermodethat has not yet been addressed.The last rendering mode option is
@rendermode InteractiveAuto. This mode tries to combine the benefits of Blazor Server's quick response, with the fully client hosted Blazor WebAssembly.When a user initially visits a page marked as
InteractiveAuto, the server renders the page using Blazor Server while simultaneously downloading the WebAssembly package in the background. During this initial visit, the component operates as a Blazor Server component, utilizing the SignalR connection. Upon the user's subsequent visit to this page, it will be rendered using Blazor WebAssembly.🔀 Auto Trade-offs
**** The Auto rendering mode is designed to rapidly provide users with an interactive page while ultimately leveraging the WebAssembly rendering mode.Duplicated Processes
However, a key trade-off to consider with this model is the accessibility differences between each mode. The Server mode can directly interact with server logic, whereas the WebAssembly mode requires API calls for communication. Consequently, you'll need to develop two distinct processes for each rendering mode to interact with server resources.
The need for duplicated server access logic should be carefully weighed when considering the implementation of the InteractiveAuto rendering mode.
Testing Challenges
Testing this feature presents additional challenges. To effectively test the Blazor Server path, you will need to delete the WebAssembly package from the browser after each test.
Due to this challenge, the demonstration of this rendering mode option has been omitted from this lab.
However, if you are comfortable with your browser's developer tools, you are encouraged to experiment on your own. Simply declare the
@rendermode InteractiveAutodirective and then manually remove the downloaded WebAssembly package using the developer tools.Congratulations
Congratulations on finishing this lab.
Hopefully this introduction to the different rendering modes has helped to provide you with a good idea of the benefits and trade-offs of using the various rendering modes within your application.
The best as you continue your Blazor learning journey. Looking forward to seeing what you create.
About the author
Real skill practice before real-world application
Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.
Learn by doing
Engage hands-on with the tools and technologies you’re learning. You pick the skill, we provide the credentials and environment.
Follow your guide
All labs have detailed instructions and objectives, guiding you through the learning process and ensuring you understand every step.
Turn time into mastery
On average, you retain 75% more of your learning if you take time to practice. Hands-on labs set you up for success to make those skills stick.