Introduction
In my previous blog we talked about Blazor, the 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 that has the UI components separate so that we can reuse those in both WebAssembly & Blazor servers.
Step 1. Open Visual Studio 2019 to see the following start screen and then click on "Create New Project" as highlighted in the screenshot.
Step 2. On the Create a new project window, enter or type Razor Class in the search box. It will show the Razor Class Library project on top, click on that and then click Next as shown below screenshot.
Step 3. Next, we will get below screen, mention the name of the project, and its path, and click on Create as highlighted.
Step 4. Next, we will get the following screen where we have to un-check Support Pages and Views as highlighted and click on the Create button.
Step 5. The default-created project will have the following structure.
Step 6. Rename Component1.razor (highlighted in the previous screenshot) to App.Razor and replace its code with the following code.
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
Step 7. Replace the default code of _Imports.razor with the following code.
@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
@using BlazorComponents
@using BlazorComponents.Shared
@using BlazorComponents.Pages
Step 8. Add two Folders named Pages & Shared. The project will have the following structure now
Step 9. Right-click on the Shared folder and click on Add => New Item on the context menu as highlighted in the below screenshot.
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.
Step 11. Replace the default code of MainLayout.razor with the following code.
@inherits LayoutComponentBase
<div class="sidebar">
<NavMenu />
</div>
<div class="main">
<div class="top-row px-4">
<a href="https://docs.microsoft.com/en-us/aspnet/" target="_blank">About</a>
</div>
<div class="content px-4">
@Body
</div>
</div>
Step 12. Repeat Steps 9 & 10 to create NavMenu.razor.
Step 13. Replace the default code of NavMenu.razor with the following code.
<div class="top-row pl-4 navbar navbar-dark">
<a class="navbar-brand" href="">BalzeServer</a>
<button class="navbar-toggler" @onclick="ToggleNavMenu">
<span class="navbar-toggler-icon"></span>
</button>
</div>
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
<ul class="nav flex-column">
<li class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="oi oi-home" aria-hidden="true"></span> Home
</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="oi oi-plus" aria-hidden="true"></span> Counter
</NavLink>
</li>
<li class="nav-item px-3">
<NavLink class="nav-link" href="fetchdata">
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
</NavLink>
</li>
</ul>
</div>
@code {
private bool collapseNavMenu = true;
private string NavMenuCssClass => collapseNavMenu ? "collapse" : null;
private void ToggleNavMenu()
{
collapseNavMenu = !collapseNavMenu;
}
}
Step 14. Repeat Steps 9 & 10 on Pages Folder and create Index.razor.
Step 15. Replace the default code of Index.razor with the following code.
@page "/"
<h1>Hello, world!</h1>
Welcome to your new app.
Step 16. Repeat Steps 9 & 10 on Pages Folder and create Counter.razor.
Step 17. Replace the default code of Counter.razor with the following code.
@page "/counter"
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}
Now our component library is ready we have recreated the default Template code in a Razor Component Library code. Now follow the 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.
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.
Step 5. Right-click on the BlazorServer project and select Add => Reference.. from the context menu as shown below,
Step 6. Add the reference of the BlazorComponents project as shown below.
Step 7. As mentioned in Step 9 above click on the BlazorServer project and select Add => New Item from the context menu.
Step 8. From the New Item Dialog box select Razor Page and name it as _Host.cshtml as shown below.
Step 9. Replace the code of _Host.cshtml with the below code.
@page "/"
@namespace BlazorComponents
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BlazorServer</title>
<base href="~/" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="css/site.css" rel="stylesheet" />
</head>
<body>
<app>
@(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
</app>
<script src="_framework/blazor.server.js"></script>
</body>
</html>
Step 10. Open StartUp.cs and update its ConfigureServices method with the following code. In this code, we are adding MVC support to the Blazor application and setting the default path for Razor Pages (the first two lines of the method).
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddRazorPagesOptions(options => { options.RootDirectory = "/"; });
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
}
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 the same as the output from the default Blazor Template.
In this blog, we learned about how we can create an external component library with code the same as the Blazor Default template and use that external component library in the Blazor Server application. This application architecture is now future-ready as we can use the same UI code for another project like Blazor WebAssembly but that's 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.