Hello everyone, I am a wolf at the end of the desert.
The Dotnet 9 website has returned to Blazor reconstruction, and the access speed is indeed fast. At the same time, using Blazor's interactive capabilities, the webmaster has also added several online tools simultaneously. This article shares the Blazor reconstruction process, hoping to provide a reference for everyone when developing their website. Make technical selection.

1. Let's start with Razor Pages
The last version of the website used Razor Pages development at the front desk. At that time, this technology stack was mainly selected for the sake of SEO optimization of search engines.
Regarding which is better, MVC or Razor Pages, we only talk about the relative advantages of Razor Pages.
First of all, Razor Pages is simpler and more intuitive than MVC. Because Razor Pages encapsulates views and processing logic in the same page, developers can more easily understand and maintain code. For small projects or applications with only a small number of pages, Razor Pages can provide faster development speeds and a simpler code structure, which was the main reason why webmasters chose to rebuild Razor Pages from MVC at the time.
Secondly, Razor Pages has certain advantages in SEO (Search Engine Optimization). Because Razor Pages encapsulates views and processing logic on the same page, search engines can more easily understand and index the content of the page. This is an important consideration for applications that require better search engine rankings.
Speaking of Razor Pages's advantages, why switch to Blazor now? Because Blazor might be a better choice again, we went on.
2. Key talk about Blazor
Blazor is an emerging web development framework that allows developers to use the C#language to write web applications without using JavaScript. Of course, it can only be said to use it as little as possible, and it is not realistic to use it at all. Compared with Razor Pages and MVC, Blazor provides a new development model with many unique advantages and application scenarios.
First, Blazor provides a true front-end development experience. In traditional Web development, front-end developers need to use JavaScript to handle page interactions and dynamic effects, while back-end developers are responsible for handling business logic and data operations. This separate development model can cause communication and collaboration issues among developers. Blazor uses the C#language to write front-end code, allowing front-end and back-end developers to use the same language and tools to collaborate in development more efficiently.
Secondly, Blazor provides better performance and user experience. Blazor provides two models: client and server (we will talk about Blazor hybrid model when we have the opportunity):
- Client mode: Blazor uses WebAssembly technology to run compiled binary code directly in the browser, achieving performance close to native applications.
- Server-side model: Compared with traditional HTTP request-based page refreshes, Blazor uses a SignalR connection to achieve real-time data updates and two-way binding, which can provide a faster and smoother user experience.
In addition, Blazor also has better reusability and component-based development. Blazor provides a rich library of components and tools that help developers build beautiful and powerful interfaces faster. Developers can encapsulate commonly used UI components into reusable components to improve development efficiency and code quality.
In addition, Blazor also supports modern front-end development technologies and tools. Developers can use Blazor to integrate with existing JavaScript libraries and frameworks, such as React, Vue.js, etc.
Overall, Blazor is a better choice for Razor Pages and MVC, especially for projects that require a better front-end development experience, better performance and user experience, and better reusability and component-based development. However, the choice of which development model to use still depends on the specific needs of the project and the preferences of the development team. No matter which model you choose, it is important to make reasonable choices based on the actual situation of the project and follow good design principles and best practices during the development process.
3. Let's talk about why we use Blazor again?
The webmaster developed a version of the website using Blazor Server last year. At that time, due to the disconnection and reconnection experience, the webmaster chose to rebuild it with Razor Pages.
The turning point for webmasters to return to Blazor this time was June 13-the release of. NET 8 Preview 5. The VS2022 preview version also released the Blazor Web App project template. Various technical groups also discussed it crazy. Webmasters added Razor components to Razor Pages. Microsoft is really awesome, aiming to make the Blazor component meet all web UI requirements of the client and server.
但目前该模式Razor组件无法交互,页面还出现了重连置灰UI,索性直接用Blazor Server重构,经过几天的奋战,网站前台已经用Blazor Server完全替换Razor Pages,烦人的重连也解决了,现在访问网站飞快,不知道是不是错觉,个人感觉很好。(重连问题参考微软文档【ASP.NET Core BlazorSignalR 指南】和Token佬写的文章 【如何取消Blazor Server烦人的重新连接?】。)
Razor Pages (MVC) and Blazor both use Razor syntax, so in theory, the switching is seamless, and the core code has not changed much. For a comparison of the structure of the project code file, see the screenshot below, and I won't go into it again. If you are interested in looking at the source code, both versions of the code are there.
| Razor Pages Engineering Architecture | Blazor Server Edition Engineering Structure |
![]() |
![]() |
4. Blazor's interactivity convenience: bringing several online tools
For page event processing, it is convenient to use Blazor. Here are the 4 widgets added last night:

Interested friends can click to experience it: https://dotnet9.com/tools. We directly post 4 widget codes. You may like Blazor's code style.
4.1. JSON formatting
Access address: https://www.example.com

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="输入Json" Rows="8" style="font-size:12px;" RowHeight="15" AutoGrow/>
</div>
<div>
<MButton Color="success" class="ma-2" OnClick="() => FormatJson(true)">格式化</MButton>
<MButton Color="lime" OnClick="() => FormatJson(false)">压缩</MButton>
</div>
<div>
<MTextarea BackgroundColor="amber lighten-4" Solo
Color="orange orange-darken-4" TValue="string" @bind-Value="_formattedJson"
Label="格式化或压缩后Json" Rows="8" style="font-size:12px;" RowHeight="15" AutoGrow/>
</div>
</MApp>
@code
{
private const string? _title = "工具箱-JSON格式化";
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 = "无效的JSON格式";
}
}
}
4.2. Online string encoding tool
Access address: https://www.example.com

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="输入字符串"/>
</p>
<p>
<MTextarea BackgroundColor="amber lighten-4" Solo
Color="orange orange-darken-4" TValue="string" @bind-Value="_encodedOrDecodeString"
Label="编/解码结果"/>
</p>
<p>
<MButton OnClick="@Encode">编码</MButton>
<MButton OnClick="@Decode">解码</MButton>
<MButton OnClick="@Clear">清空</MButton>
</p>
</MApp>
@code {
private const string Title = "工具箱-在线字符串编码工具";
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 address: https://www.example.com

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="持续时间(秒)" Type="number" TValue="int" @bind-Value="@_duration"/>
</p>
<p>
<MButton Color="success" class="ma-2" OnClick="@StartCountdown" Disabled="@_isCountingDown">开始</MButton>
<MButton Color="pink" class="ma-2 white--text" OnClick="@PauseCountdown" Disabled="!_isCountingDown">暂停</MButton>
<MButton Color="deep-orange" class="ma-2 white--text" OnClick="@ResetCountdown" Disabled="!_isCountingDown">重置</MButton>
剩余时间(秒):@_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 = "工具箱-倒计时";
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 address: https://www.example.com
站长原来写过一篇,可以看这里:使用Blazor做个简单的时间戳在线转换工具。
5. summary
There may be bugs in the website, no, there must be bugs, and the webmaster will keep reconstructing and iterating.
I am very happy to restructure the front desk of the website and share this joy with you, and wish you all a healthy Dragon Boat Festival.
- Website address: https://www.example.com
- Website source code: https://www.example.com
- .NET版本: .NET 8.0.0-preview.5.23280.8

