Future Ready Blazor Application Architecture

In my previous blog we talked about Blazor, defaults Blazor project templates available with .NET Core and how to create Blazor application 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 increase the code reuse as we can used same components for both Blazor.Server & Blazor WASM based applications. 

The code given by 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.

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.

Step-3: Next we will get below screen, mention the name of project, it's path and click on Create as highlighted.

Step-4:  Next we will get following screen where we have to un-check Support Pages and Views as highlighted and click on Create button.

Step-5: The default created project will have following structure:

Step-6: Rename Component1.razor  (highlighted in previous screenshot) to App.Razor and replace it's code with 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 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 following structure now :

Step-9: Right click on Shared folder click on Add => New Item on the context menu as highlighted in below screenshot.

Step-10:  Next following screen will appear to select the new Item type. select Razor Component, name it as  and click on Add as highlighted.


Step-11:  Replace the default code of MainLayout.razor with 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 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  again on Pages Folder and create Index.razor.

Step-15:  Replace the default code of Index.razor with following code:

@page "/"

<h1>Hello, world!</h1>

Welcome to your new app.

Step-16:  Repeat the Steps 9 & 10  again on Pages Folder and create Counter.razor.

Step-17:  Replace the default code of Counter.razor with 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, 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:

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 following.

Step-5: Right click on BlazorServer project and select Add => Reference.. from context menu as shown below:

Step-6: Add the reference of  BlazorComponents project as shown below.

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.

Step-9: Replace the code of _Host.cshtml with 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 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).

        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 following output which is exactly same as the output from default Blazor Template. 

 In this blog we learned about how we can create a external component library with code same 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

S Ravi Kumar

Ravi is an experienced IT professional with over 15 years of IT services experience using Microsoft technologies including like ASP.Net, C#, .Net Core, Xamarin.Forms, Azure etc.

Add a new comment

 

Comments