Dotnet9 Website Returns to Blazor Refactoring, Access Speed Soars, and Interaction is More Convenient!

Dotnet9 Website Returns to Blazor Refactoring, Access Speed Soars, and Interaction is More Convenient!

Originally, the site owner aimed to experience .NET 8 Blazor Web App by adding Razor components to Razor Pages. However, the hybrid mode Razor components currently cannot interact, and the page also shows a reconnection gray UI. So, they simply used Blazor Server for refactoring. After days of hard work, the website's front-end has been completely replaced with Blazor Server over Razor Pages, and the annoying reconnection issue has been resolved. Now the website loads very fast, though it might be an illusion, but personally it feels great.

Last updated 6/23/2023 9:10 AM
沙漠尽头的狼
10 min read
Category
Blazor
Tags
.NET C# Blazor Razor Pages Dotnet9

Hello everyone, I'm Wolf at the End of the Desert.

The Dotnet9 website has been rebuilt with Blazor, and the access speed is really fast. At the same time, leveraging Blazor's interactive capabilities, the site owner has also added several online tools. This article shares the process of rebuilding with Blazor, hoping to provide a reference for everyone when making technical choices for website development.

1. First, a Word on Razor Pages

The previous version of the website frontend used Razor Pages. At the time, this technology stack was chosen mainly for SEO optimization.

Regarding which is better between MVC and Razor Pages, we'll only discuss the relative advantages of Razor Pages here.

First, Razor Pages is simpler and more intuitive compared to MVC. Because Razor Pages encapsulates both the view and processing logic in the same page, developers can more easily understand and maintain the code. For small projects or applications with only a few pages, Razor Pages can provide faster development speed and cleaner code structure—this was the main reason the site owner chose to refactor from MVC to Razor Pages.

Second, Razor Pages has certain advantages in SEO (Search Engine Optimization). Since Razor Pages encapsulate view and processing logic in the same page, search engines can more easily understand and index the page content. This is an important consideration for applications that need better search engine rankings.

So, if Razor Pages has advantages, why switch to Blazor now? Because Blazor might be an even better choice—let's continue.

2. The Key Point: Let's Talk About Blazor

Blazor is an emerging web development framework that allows developers to write web applications using the C# language without necessarily using JavaScript. Well, we can say "minimizing" the use of JavaScript; completely avoiding it is not realistic. Compared to Razor Pages and MVC, Blazor offers a completely new development model with many unique advantages and suitable scenarios.

First, Blazor provides a true frontend development experience. In traditional web development, frontend developers use JavaScript to handle page interactions and dynamic effects, while backend developers handle business logic and data operations. This separation can lead to communication and collaboration issues between developers. Blazor uses C# to write frontend code, allowing frontend and backend developers to use the same language and tools, enabling more efficient collaborative development.

Second, Blazor offers better performance and user experience. Blazor provides two modes: client-side and server-side (we'll discuss Blazor hybrid mode another time):

  • Client-side mode: Blazor uses WebAssembly technology to run compiled binary code directly in the browser, achieving performance close to native applications.
  • Server-side mode: Compared to traditional page refreshes based on HTTP requests, Blazor uses SignalR connections for real-time data updates and two-way binding, providing a faster and smoother user experience.

Additionally, Blazor has better reusability and component-based development. Blazor provides a rich set of component libraries and tools that help developers quickly build beautiful and powerful interfaces. Developers can encapsulate commonly used UI components into reusable components, improving development efficiency and code quality.

Moreover, Blazor supports modern frontend development technologies and tools. Developers can integrate Blazor with existing JavaScript libraries and frameworks, such as React, Vue.js, etc.

In summary, Blazor is a better choice compared to Razor Pages and MVC, especially for projects that require a better frontend development experience, better performance and user experience, and better reusability and component-based development. However, choosing which development model to use still depends on the specific needs of the project and the preferences of the development team. Regardless of the model chosen, it's important to make a reasonable decision based on the project's actual situation and follow good design principles and best practices during development.

3. Let's Talk Again: Why Use Blazor Again?

Last year, the site owner developed a version of the website frontend using Blazor Server. At that time, due to the problematic reconnection experience, the site owner chose to refactor with Razor Pages.

The turning point for the site owner to return to Blazor was on June 13th - the release of .NET 8 Preview 5. The VS2022 preview also released the Blazor Web App project template, and various tech communities went wild discussing it. The site owner tried adding Razor components to Razor Pages. Microsoft is truly impressive—they aim to make Blazor components meet all web UI needs on both client and server sides.

But currently, Razor components in this mode cannot interact, and the page also shows a reconnection grayed-out UI. So the site owner simply refactored using Blazor Server directly. After several days of hard work, the website frontend has been completely replaced with Blazor Server from Razor Pages. The annoying reconnection issue is also resolved. Now the website is very fast to access—maybe it's an illusion, but personally, it feels great. (Regarding the reconnection issue, refer to Microsoft documentation ASP.NET Core Blazor SignalR guidance and the article by Token How to cancel the annoying reconnection of Blazor Server?.)

Both Razor Pages (MVC) and Blazor use Razor syntax, so theoretically, switching is seamless with minimal changes to core code. The project code file structure comparison is shown in the screenshot below. I won't go into detail—check the source code if interested; both versions of the code are available.

Razor Pages version project structure Blazor Server version project structure

4. Interaction Convenience of Blazor: Bringing a Few Online Tools

For page event handling, using Blazor is convenient. Below are four small tools added last night:

Interested friends can click to try: https://dotnet9.com/tools. We'll directly paste the code for the four tools—you might fall in love with Blazor's coding style.

4.1. JSON Formatter

Access URL: https://dotnet9.com/tools/jsonformatter

Page code:

@page "/tools/jsonformatter"
@using System.Text.Json

<PageTitle>@_title</PageTitle>

<MApp>
   <h2 style="margin-bottom: 30px; margin-top: 10px; text-align: center;">@_title</h2>

   <div>
       <MTextarea BackgroundColor="grey lighten-2" Solo
                  Color="orange orange-darken-4" TValue="string" @bind-Value="_inputJson"
                  Label="Enter JSON" Rows="8" style="font-size:12px;" RowHeight="15" AutoGrow/>
   </div>

   <div>
       <MButton Color="success" class="ma-2" OnClick="() => FormatJson(true)">Format</MButton>
       <MButton Color="lime" OnClick="() => FormatJson(false)">Compress</MButton>
   </div>

   <div>
       <MTextarea BackgroundColor="amber lighten-4" Solo
                  Color="orange orange-darken-4" TValue="string" @bind-Value="_formattedJson"
                  Label="Formatted or Compressed JSON" Rows="8" style="font-size:12px;" RowHeight="15" AutoGrow/>
   </div>
</MApp>

@code
{
       private const string? _title = "Tools - JSON Formatter";
   private string? _inputJson;
   private string? _formattedJson;

   private void FormatJson(bool writeIndented)
   {
       try
       {
           var jsonObject = JsonDocument.Parse(_inputJson).RootElement;
           _formattedJson = JsonSerializer.Serialize(jsonObject, new JsonSerializerOptions { WriteIndented = writeIndented });
       }
       catch (JsonException)
       {
           _formattedJson = "Invalid JSON format";
       }
   }
}

4.2. Online String Encoding Tool

Access URL: https://dotnet9.com/tools/string-encoder

Page code:

@page "/tools/string-encoder"

<PageTitle>@Title</PageTitle>

<MApp>
   <h2 style="margin-bottom: 30px; margin-top: 10px; text-align: center;">@Title</h2>

   <p>
       <MTextarea BackgroundColor="grey lighten-2"
                  Color="cyan" Solo TValue="string" @bind-Value="_inputString"
                  Label="Enter string"/>
   </p>

   <p>
       <MTextarea BackgroundColor="amber lighten-4" Solo
                  Color="orange orange-darken-4" TValue="string" @bind-Value="_encodedOrDecodeString"
                  Label="Encode/Decode result"/>
   </p>

   <p>
       <MButton OnClick="@Encode">Encode</MButton>
       <MButton OnClick="@Decode">Decode</MButton>
       <MButton OnClick="@Clear">Clear</MButton>
   </p>
</MApp>

@code {
   private const string Title = "Tools - Online String Encoding Tool";
   private string? _inputString;
   private string? _encodedOrDecodeString;

   private void Encode()
   {
       _encodedOrDecodeString = System.Web.HttpUtility.UrlEncode(_inputString);
   }

   private void Decode()
   {
       _encodedOrDecodeString = System.Web.HttpUtility.UrlDecode(_inputString);
   }

   private void Clear()
   {
       _inputString = string.Empty;
       _encodedOrDecodeString = string.Empty;
   }

}

4.3. Countdown

Access URL: https://dotnet9.com/tools/countdown

Page code:

@page "/tools/countdown"

<PageTitle>@Title</PageTitle>

<MApp>
   <h2 style="margin-bottom: 30px; margin-top: 10px; text-align: center;">@Title</h2>

   <p>
       <MTextField Label="Duration (seconds)" Type="number" TValue="int" @bind-Value="@_duration"/>
   </p>

   <p>
       <MButton Color="success" class="ma-2" OnClick="@StartCountdown" Disabled="@_isCountingDown">Start</MButton>
       <MButton Color="pink" class="ma-2 white--text" OnClick="@PauseCountdown" Disabled="!_isCountingDown">Pause</MButton>
       <MButton Color="deep-orange" class="ma-2 white--text" OnClick="@ResetCountdown" Disabled="!_isCountingDown">Reset</MButton>
       Remaining time (seconds): @_remainingTime
   </p>
   <div class="text-center">
       <MProgressCircular Value="@_remainingTimePercent" Size="100" Width="15" Rotate="360" Color="teal">@_remainingTime</MProgressCircular>
   </div>
</MApp>

@code {
   private const string Title = "Tools - Countdown";
   private int _duration = 20;
   private int _remainingTime;
   private int _remainingTimePercent;
   private bool _isCountingDown;
   private bool _isPause;
   private CancellationTokenSource? _countdownTokenSource;

   private async Task StartCountdown()
   {
       if (_duration < 0)
       {
           _duration = 10;
       }
       if (_isCountingDown)
       {
           return;
       }
       _isCountingDown = true;
       if (!_isPause || _remainingTime <= 0)
       {
           _remainingTime = _duration;
           ChangeRemainingTimePercent();
       }
       _countdownTokenSource = new CancellationTokenSource();

       await Countdown(_countdownTokenSource.Token);
   }

   private void PauseCountdown()
   {
       if (!_isCountingDown)
       {
           return;
       }
       _isCountingDown = false;
       _isPause = true;
       _countdownTokenSource?.Cancel();
   }

   private async void ResetCountdown()
   {
       _isPause = false;
       if (_isCountingDown && _countdownTokenSource != null)
       {
           await _countdownTokenSource.CancelAsync();
       }

       _remainingTime = _duration;
       _isCountingDown = false;
       ChangeRemainingTimePercent();
   }

   private async Task Countdown(CancellationToken cancellationToken)
   {
       while (_remainingTime > 0)
       {
           await Task.Delay(1000, cancellationToken);
           _remainingTime--;
           ChangeRemainingTimePercent();

           if (cancellationToken.IsCancellationRequested)
           {
               return;
           }
       }

       _isCountingDown = false;
   }

   private async void ChangeRemainingTimePercent()
   {
       _remainingTimePercent = (int)(_remainingTime * 100.0 / _duration);
       await InvokeAsync(StateHasChanged);
   }

}

4.4. Timestamp Conversion

Access URL: https://dotnet9.com/tools/timestamp

The site owner wrote an article about this before—check it out here: Use Blazor to make a simple online timestamp conversion tool.

5. Summary

There may be bugs on the website—no, there definitely are bugs—and the site owner will continue to refactor and iterate.

I am very glad to share this joy of refactoring the website frontend with everyone. Wishing everyone a happy Dragon Boat Festival.

Keep Exploring

Related Reading

More Articles
Same category / Same tag 11/6/2024

Why My Blog Website Returned to Blazor

The development of the blog website has gone through many hardships, with nearly 10 versions including MVC, Vue, Go, etc. Now it has returned to Blazor and adopted static SSR, resulting in a significant speed increase and successful launch.

Continue Reading
Same category / Same tag 2/29/2024

Data Display Can Also Be Done Like This in Winform

In the process of developing Winform, data display functionality is often required. Previously, the gridcontrol control was commonly used. Today, through an example, I would like to introduce how to use the table component from Ant Design Blazor for data display in a Winform Blazor Hybrid application.

Continue Reading
Same category / Same tag 2/29/2024

Can the Winform interface also look good?

A few days ago, I introduced using Blazor Hybrid in Winform, and mentioned that with the Blazor UI, our Winform programs can be designed to look better. Next, I will illustrate with an example of drawing in Winform Blazor Hybrid, hoping it helps you.

Continue Reading