使用 Razor Pages 打造查看真实 IP、IPv6 检测网站系列文章:
本篇文章对应的代码可以在 https://github.com/huhubun/BunIp/tree/simple_ver 查看到。
完整实现可以访问 https://ip.bun.plus/ 体验。
背景
我主要使用的主机是腾讯云,可惜腾讯云目前没有提供免费的 IPv6 给虚拟机(呐,有点过分唉,阿里云和 Vultr 明明都有的),所以把闲置的树莓派利用起来!
IPv6 一大亮点就是不再需要折腾内网穿透,如果获得的是公网 IPv6,即便把树莓派放在家里,其他拥有公网 IPv6 的人也可以直接访问到的~美滋滋。
使用 C# 获取树莓派型号
通过搜索,我了解到访问 /proc/device-tree/model
即可获得树莓派的型号:
$ cat /proc/device-tree/model
Raspberry Pi 3 Model B Rev 1.2
因为这是个文本文件,所以只需要用 File
去读取即可。在 Helpers
文件夹中新建 PiHelper.cs
:
using System.IO;
namespace IpTest.Helpers
{
public static class PiHelper
{
const string MODEL_PATH = "/proc/device-tree/model";
const string MODEL_PREFIX = "Raspberry Pi";
/// <summary>
/// 获取树莓派版本号
/// </summary>
/// <returns></returns>
public static string GetModel()
{
if (File.Exists(MODEL_PATH))
{
var model = File.ReadAllText(MODEL_PATH).TrimEnd((char)0);
if (model.StartsWith(MODEL_PREFIX))
{
return model;
}
}
return null;
}
}
}
这个方法首先判断了 /proc/device-tree/model
是否存在,如果存在的话就读取其中所有文本(我的树莓派读取的内容最后有一个 ASCII 为 0
的字符,需要将其去除,否则网页上会显示成乱码),如果 model 的内容以 Raspberry Pi
开头则说明是树莓派,返回型号,否则返回 null
。
接着我们来到 /Pages/Shared/_Layout.cshtml
文件,在 <footer>
部分显示出树莓派型号,修改后的 <footer>
如下:
<footer class="border-top footer text-muted">
<div class="container">
© 2020 - IpTest - <a asp-area="" asp-page="/Privacy">Privacy</a>
@{
var piModel = IpTest.Helpers.PiHelper.GetModel();
}
@if (piModel != null)
{
<span class="float-right">Powered by @piModel</span>
}
</div>
</footer>
通过 View Component(视图组件)模块化代码
在上一步中,我们在 _Layout.cshtml
里添加了获取树莓派型号的代码,但实际上通过什么方法获取模型、什么时候应该显示模型,其实不属于 _Layout.cshtml
的工作,现在的做法导致 _Layout.cshtml
和获取型号的逻辑耦合在了一起。
使用过 vue 等框架的朋友一定体验过自定义组件的方便性。在 ASP.NET Core 中提供了 View Component(视图组件),它可以配合 Tag Helpers,就可以实现将获取型号的代码单独放在一个名为 PiModel
的组件中,然后在 _Layout.cshtml
中添加一个类似 HTML 标签的东西 <pi-model />
,从而让逻辑互相独立。
除了让各个部分的逻辑保持独立互不干扰外,对于可重用的内容也非常适合使用组件来实现,这里只是抛砖引玉将显示树莓派模型这么一个小功能做成组件。
创建 View Component
在 /Pages/Shared
文件夹下新增一个名为 Components
的文件夹,默认情况下 Razor Pages 会从这里加载组件。接着在 Components
文件夹里新建一个名为 PiModel
的文件夹,用于实现我们的树莓派型号组件。
视图组件包含三个部分:
- 显示部分,用于输出页面呈现的内容。右键单击
PiModel
文件夹,依次选择添加
-新建项
-ASP.NET Core
-Razor 视图 - 空
,命名为Default.cshtml
。 注意是 Razor 视图,而不是 Razor 页面! - 逻辑部分,用于实现相关业务逻辑。在
PiModel
文件夹中添加一个名为PiModelViewComponent
的类。这个类的名字会和 Tag Helpers 有关联,当类名ViewComponent
之前的部分将成为 Tag Helper 的名称。当我们想要<pi-model>
这样的标签就需要按大小写(首字母和每个连字符后的字母需要大写)创建类的名称:PiModel
,所以连在一起就是PiModelViewComponent
。 - 模型部分,用于在业务逻辑部分和显示部分中传递数据。在
PiModel
文件夹中添加一个名为ViewModel
的类即可。
有点像一个缩小版的 MVC…完整的效果如下:
实现 View Component 中的业务代码
首先我们实现 ViewModel
,因为它是业务和显示之间的纽带。这里只有一个存储了树莓派型号的字符串需要传递,那么就在 ViewModel
中新建一个字符串类型的属性即可:
namespace IpTest.Pages.Shared.Components.PiModel
{
public class ViewModel
{
public string PiModel { get; set; }
}
}
接着实现 PiModelViewComponent
,它必须派生自 ViewComponent
类才会被识别为视图组件;然后为它添加一个 Invoke()
方法,并在其中填充 ViewModel
并通过 View()
返回:
using IpTest.Helpers;
using Microsoft.AspNetCore.Mvc;
namespace IpTest.Pages.Shared.Components.PiModel
{
public class PiModelViewComponent : ViewComponent
{
public IViewComponentResult Invoke()
{
return View(new ViewModel
{
PiModel = PiHelper.GetModel()
});
}
}
}
当使用视图组件时,会触发 Invoke()
方法。这个方法还有一个异步版本 InvokeAsync()
,可以通过视图组件方法了解。
然后把显示部分实现,修改 Default.cshtml
:
@model IpTest.Pages.Shared.Components.PiModel.ViewModel
@if (Model.PiModel != null)
{
<span class="float-right">Powered by @Model.PiModel</span>
}
我们还得在 _ViewImports.cshtml
文件中把刚刚创建的视图组件导入为 Tag Helper,在文件末尾增加:
@addTagHelper *, IpTest
代码最后的 IpTest
是我们的程序集名称,这样能够导入整个程序集里所有的 Tag Helper。
最后来到 _Layout.cshtml
文件,把之前在 <footer>
里增加的代码删除,改为我们的组件。最终 <footer>
部分如下:
<footer class="border-top footer text-muted">
<div class="container">
© 2020 - IpTest - <a asp-area="" asp-page="/Privacy">Privacy</a>
<vc:pi-model />
</div>
</footer>
视图组件的 Tag Helper 以 vc:
开头,然后我们的组件类为 PiModelViewComponent
,还记得上面说的命名约定吧,PiModel
会转换为 pi-model
,所以标签写成 <vc:pi-model>
。
最终页面的访问效果:
为树莓派安装 .NET 5
树莓派需要使用手动安装的方式,目前不能通过包管理器安装。我使用的是树莓派3代,安装了 Raspberry Pi OS (32-bit),所以我需要使用 32 位的 .NET 5 Runtime。
访问 https://dotnet.microsoft.com/download/dotnet/5.0 下载最新的 .NET 5 Arm32 Runtime 到树莓派上,然后参考 在 Debian 上手动安装 的方案:
sudo mkdir -p "$HOME/dotnet" && tar zxf aspnetcore-runtime-5.0.0-linux-arm.tar.gz -C "$HOME/dotnet"
export DOTNET_ROOT=$HOME/dotnet
export PATH=$PATH:$HOME/dotnet
然后查看安装情况
dotnet --info
如果返回了正确的运行时版本说明安装成功。
由于使用 export
命令只会使环境变量在当前会话生效,还需要根据你使用的 shell 修改对应的配置文件保证每次会话都能正常使用 dotnet
命令。请参考 在 Debian 上手动安装 的 提示 部分进行配置。
偷偷告诉大家…我直接解压到
/usr/bin/dotnet
里面了,就不用配 bashrc 之类的了 😅
这期文章到这里就结束了,如果大家部署了好玩的站点别忘了通过微信公众号告诉我哦~