Future Ready Blazor Application Architecture

Introduction 

 
In my previous blog we talked about Blazor, default Blazor project templates available with .NET Core, and how to create Blazor applications using those templates in Visual Studio 2019. At the end of the blog I also mentioned that Blazor uses ASP.NET Core Razor Components for creating the UI which increases the code reuse as we can use the same components for both Blazor.Server & Blazor WASM based applications.
 
The code given by the current default Blazor Templates includes the components code inside them. In this blog we will learn to create a Blazor application which has the UI components separate so that we can reuse those in both WebAssembly & Blazor server.
 
Step 1
 
Open Visual Studio 2019 to see following start screen and then click on "Create New Project" as highlighted in screenshot.
 
Future Ready Blazor Application Architecture 
 
Step 2
 
On the Create a new project window, enter or type Razor Class in the search box. It will show Razor Class Library project on top, click on that and then click Next as shown in below screenshot.
 
Future Ready Blazor Application Architecture
 
Step 3
 
Next we will get below screen, mention the name of project, its path and click on Create as highlighted.
 
Future Ready Blazor Application Architecture
 
Step 4
 
Next we will get  the following screen where we have to un-check Support Pages and Views as highlighted and click on Create button.
 
Future Ready Blazor Application Architecture
 
Step 5
 
The default created project will have the following structure.
 
Step 6
 
Rename Component1.razor (highlighted in previous screenshot) to App.Razor and replace its code with the following code,
  1. <Router AppAssembly="@typeof(App).Assembly">  
  2.     <Found Context="routeData">  
  3.         <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />  
  4.     </Found>  
  5.     <NotFound>  
  6.         <LayoutView Layout="@typeof(MainLayout)">  
  7.             <p>Sorry, there's nothing at this address.</p>  
  8.         </LayoutView>  
  9.     </NotFound>  
  10. </Router>  
Step 7
 
Replace the default code of _Imports.razor with the following code,
  1. @using System.Net.Http  
  2. @using Microsoft.AspNetCore.Authorization  
  3. @using Microsoft.AspNetCore.Components.Forms  
  4. @using Microsoft.AspNetCore.Components.Routing  
  5. @using Microsoft.AspNetCore.Components.Web  
  6. @using Microsoft.JSInterop  
  7. @using BlazorComponents  
  8. @using BlazorComponents.Shared  
  9. @using BlazorComponents.Pages  
Step 8
 
Add two Folders named Pages & Shared. The project will have the following structure now,
 
Future Ready Blazor Application Architecture
 
Step 9
 
Right click on Shared folder click on Add => New Item on the context menu as highlighted in the below screenshot.
 
Future Ready Blazor Application Architecture
 
Step 10
 
Next the following screen will appear to select the new Item type. Select Razor Component, name it and click on Add as highlighted.
 
Future Ready Blazor Application Architecture
 
Step 11
 
Replace the default code of MainLayout.razor with the following code,
  1. @inherits LayoutComponentBase  
  2.   
  3. <div class="sidebar">  
  4.     <NavMenu />  
  5. </div>  
  6.   
  7. <div class="main">  
  8.     <div class="top-row px-4">  
  9.         <a href="https://docs.microsoft.com/en-us/aspnet/" target="_blank">About</a>  
  10.     </div>  
  11.   
  12.     <div class="content px-4">  
  13.         @Body  
  14.     </div>  
  15. </div>  
Step 12
 
Repeat Steps 9 & 10 to create NavMenu.razor.
 
Step 13
 
Replace the default code of NavMenu.razor with the following code,
  1. <div class="top-row pl-4 navbar navbar-dark">  
  2.     <a class="navbar-brand" href="">BalzeServer</a>  
  3.     <button class="navbar-toggler" @onclick="ToggleNavMenu">  
  4.         <span class="navbar-toggler-icon"></span>  
  5.     </button>  
  6. </div>  
  7.   
  8. <div class="@NavMenuCssClass" @onclick="ToggleNavMenu">  
  9.     <ul class="nav flex-column">  
  10.         <li class="nav-item px-3">  
  11.             <NavLink class="nav-link" href="" Match="NavLinkMatch.All">  
  12.                 <span class="oi oi-home" aria-hidden="true"></span> Home  
  13.             </NavLink>  
  14.         </li>  
  15.         <li class="nav-item px-3">  
  16.             <NavLink class="nav-link" href="counter">  
  17.                 <span class="oi oi-plus" aria-hidden="true"></span> Counter  
  18.             </NavLink>  
  19.         </li>  
  20.         <li class="nav-item px-3">  
  21.             <NavLink class="nav-link" href="fetchdata">  
  22.                 <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data  
  23.             </NavLink>  
  24.         </li>  
  25.     </ul>  
  26. </div>  
  27.   
  28. @code {  
  29.     private bool collapseNavMenu = true;  
  30.   
  31.     private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;  
  32.   
  33.     private void ToggleNavMenu()  
  34.     {  
  35.         collapseNavMenu = !collapseNavMenu;  
  36.     }  
  37. }  
Step 14
 
Repeat Steps 9 & 10 again on Pages Folder and create Index.razor.
 
Step 15
 
Replace the default code of Index.razor with the  following code,
  1. @page "/"  
  2. <h1>Hello, world!</h1>  
  3. Welcome to your new app.  
Step 16
 
Repeat Steps 9 & 10 again on Pages Folder and create Counter.razor.
 
Step 17
 
Replace the default code of Counter.razor with the following code,
  1. @page "/counter"  
  2. <h1>Counter</h1>  
  3. <p>Current count: @currentCount</p>  
  4. <button class="btn btn-primary" @onclick="IncrementCount">Click me</button>  
  5.   
  6. @code {  
  7.     private int currentCount = 0;  
  8.   
  9.     private void IncrementCount()  
  10.     {  
  11.         currentCount++;  
  12.     }  
  13. }  
Now our component library is ready, Basically we have recreated the default Template code in a Razor Component Library code. Now follow next Steps to use this component library in Blazor application heads.
 

Blazor.Server

 
Step 1
 
Right click on the Solution and Select Add=>New Project from the Context Menu as highlighted below,
 
Future Ready Blazor Application Architecture
 
Step 2
 
Follow the Steps 2 to 5 of this blog to create a new Blazor.Server application, name the project as BlazorServer.
 
Step 3
 
Delete Pages & Shared Folders.
 
Step 4
 
Also Delete _Import.Razor & App.Razor From the BlazorServer project root. Now the project structure will look something like the following.
 
Future Ready Blazor Application Architecture
 
Step 5
 
Right click on BlazorServer project and select Add => Reference.. from context menu as shown below,
 
Future Ready Blazor Application Architecture
 
Step 6
 
Add the reference of BlazorComponents project as shown below.
 
Future Ready Blazor Application Architecture
 
Step 7
 
As mentioned in Step 9 above right click on BlazorServer project and select Add => New Item from context menu.
 
Step 8
 
From the New Item Dialog box select Razor Page and name it as _Host.cshtml as shown below.
 
Future Ready Blazor Application Architecture
 
Step 9
 
Replace the code of _Host.cshtml with the below code,
  1. @page "/"  
  2. @namespace BlazorComponents  
  3. @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers  
  4.   
  5. <!DOCTYPE html>  
  6. <html lang="en">  
  7. <head>  
  8.     <meta charset="utf-8" />  
  9.     <meta name="viewport" content="width=device-width, initial-scale=1.0" />  
  10.     <title>BlazorServer</title>  
  11.     <base href="~/" />  
  12.     <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />  
  13.     <link href="css/site.css" rel="stylesheet" />  
  14. </head>  
  15. <body>  
  16.     <app>  
  17.         @(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))  
  18.     </app>  
  19.   
  20.     <script src="_framework/blazor.server.js"></script>  
  21. </body>  
  22. </html>  
Step 10
 
Open StartUp.cs and update it's ConfigureServices method with following code. In this code we are adding MVC support to the Blazor application and setting the default path for Razor Pages (this first two lines of the method).
  1. public void ConfigureServices(IServiceCollection services)  
  2. {  
  3.     services.AddMvc()  
  4.         .AddRazorPagesOptions(options => { options.RootDirectory = "/"; });  
  5.     services.AddRazorPages();  
  6.     services.AddServerSideBlazor();  
  7.     services.AddSingleton<WeatherForecastService>();  
  8. }  
Step 11
 
Your Blazor Server application with external component support is ready now. Execute the application now, you will get the following output which is exactly the same as the output from default Blazor Template.
 
Future Ready Blazor Application Architecture
 
In this blog we learned about how we can create a external component library with code thesame as the Blazor Default template and use that external component library in Blazor Server application. This application architecture is now future ready as we can use the same UI code for other project like Blazor WebAssembly but thats for another blog.
 
We will be extending this Code to use with Blazor WebAssembly in future blogs, the code of this project template is available here at Github.