1.2 搭建环境并追踪第一个请求


文档摘要

1.2 搭建环境并追踪第一个请求 本节动手为主:装好 .NET 8 SDK,用命令行创建第一个 Web 项目,然后给项目加上请求日志中间件,亲眼观察一个 HTTP 请求进出管线的完整轨迹——为第 2 章拆解管线做好实验台。 上一节理清了年代线,这一节把观察哨架起来。我特意不用 IDE 的图形化新建项目向导:向导把十几步操作压成一个按钮,你在结果里看不到任何过程。命令行 + 最小程序结构,才看得见请求的流动。 安装 SDK 与验证 到微软官网下载 .NET 8 SDK 安装包(Windows 用安装器,macOS/Linux 有官方脚本),装完在命令行验证: SDK 里带着运行时、编译器、项目模板和本地 Web 服务器,一个命令全齐,不需要单独装 IIS 或别的服务器——这是 ASP.

1.2 搭建环境并追踪第一个请求

本节动手为主:装好 .NET 8 SDK,用命令行创建第一个 Web 项目,然后给项目加上请求日志中间件,亲眼观察一个 HTTP 请求进出管线的完整轨迹——为第 2 章拆解管线做好实验台。

上一节理清了年代线,这一节把观察哨架起来。我特意不用 IDE 的图形化新建项目向导:向导把十几步操作压成一个按钮,你在结果里看不到任何过程。命令行 + 最小程序结构,才看得见请求的流动。

安装 SDK 与验证

到微软官网下载 .NET 8 SDK 安装包(Windows 用安装器,macOS/Linux 有官方脚本),装完在命令行验证:

# 验证 SDK 已安装,8.0.x 即为目标版本 dotnet --version # 输出示例:8.0.404 # 查看本机所有已装的运行时与 SDK dotnet --list-sdks # 输出示例: # 8.0.404 [C:\Program Files\dotnet\sdk]

SDK 里带着运行时、编译器、项目模板和本地 Web 服务器,一个命令全齐,不需要单独装 IIS 或别的服务器——这是 ASP.NET 时代做不到的事。

创建项目并解剖结构

选一个空目录,执行:

# 从模板创建空的 Web 项目,命名为 ObsStation(观察哨) dotnet new web -n ObsStation cd ObsStation dotnet run # 关键输出(留意端口,每次可能不同): # info: Microsoft.Hosting.Lifetime[14] # Now listening on: http://localhost:5173

浏览器访问那个地址,看到 "Hello World!" 就说明管线已经通了。按 Ctrl+C 停止。现在解剖这个项目的结构,为后面的观察做准备:

位置 作用 后续哪章展开
Program 程序文件 入口:建主机、注册服务、编排中间件、启动监听 第 2 章
Properties 组内的启动配置 开发环境的端口与 profile 设置 第 8 章环境部分
appsettings 配置文件 分层配置的默认来源之一 第 2 章配置节
依赖包清单文件 NuGet 依赖声明,框架本身也是一组包 第 2 章

打开入口文件,完整内容只有几行:

// 入口文件的全部内容——一个最小可运行的 ASP.NET Core 应用 var builder = WebApplication.CreateBuilder(args); // 1. 准备主机:配置、日志、容器都已就位 var app = builder.Build(); // 2. 组装应用 app.MapGet("/", () => "Hello World!"); // 3. 在管线上登记一个端点 app.Run(); // 4. 启动监听,阻塞直到进程退出

四行代码背后是一整套主机启动流程——这四行的展开正是第 2 章的主菜。现在先让它跑起来做实验。

实验:在管线上架一个计时观察哨

光看到 Hello World 不过瘾。加一段中间件代码,记录每个请求的方法、路径、状态码与耗时:

var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); // 观察哨中间件:注册在所有端点之前,因此能观察到每个请求 app.Use(async (ctx, next) => { var sw = System.Diagnostics.Stopwatch.StartNew(); await next(); // 请求继续流向管线后续各站 sw.Stop(); // 出站时输出:方法 路径 状态码 耗时 Console.WriteLine($"[哨站] {ctx.Request.Method} {ctx.Request.Path} " + $"-> {ctx.Response.StatusCode} ({sw.ElapsedMilliseconds}ms)"); }); app.MapGet("/", () => "Hello World!"); app.MapGet("/ping/{name}", (string name) => $"pong:{name}"); app.Run();

再次运行并访问几个地址,控制台输出:

[哨站] GET / -> 200 (1ms) [哨站] GET /ping/aspnet -> 200 (0ms) [哨站] GET /nope -> 404 (0ms)

三条输出值得逐条解读。第一条:请求命中根路径端点,状态码 200。第二条:路径参数 aspnet 被端点模板捕获并回显,这就是路由的最原始形态,第 3 章会展开成完整的路由系统。第三条最有意思——没有匹配端点时管线仍然完整走了一遍,哨站照样记录到 404,说明"没找到终点站"不等于"没进管线"。

观察结果的结构化视图

图 1.2-1 首个实验项目的请求旅程

图 1.2-1 首个实验项目的请求旅程

💡 关键直觉:中间件的注册顺序就是执行顺序。观察哨放在端点登记之前,所以既能看到"进站"也能看到"出站"。如果把它放在后面,404 那条日志就会消失——这个小实验预告了第 2 章的核心规则。

热重载与日常开发循环

开发期的体验优化:运行中改代码,另开终端执行:

# 热重载:不重启进程应用代码改动,观察哨的计数器等状态得以保留 dotnet watch # 输出示例: # info: Microsoft.DotNet.Watcher[0] # File changed: Program.cs # info: Microsoft.DotNet.Watcher[0] # Applying updates...

日常循环就是 dotnet watch + 浏览器刷新。需要彻底重启(改了启动配置或包引用)时再 Ctrl+C。

⚠️ 常见坑:改了端口配置但浏览器一直访问旧地址,以为是代码坏了。终端里 "Now listening on" 那一行永远以它为准,别信记忆。

问题:dotnet run 和 dotnet watch 有什么区别?

run 是"编译—启动"一次到位;watch 是常驻进程,盯着文件变化做热重载,日常开发首选。但热重载有边界:改中间件内部逻辑通常能原地生效;改了服务注册、包引用或启动配置,它会自动降级为重启进程——看到终端提示重启属于正常行为,不是故障。

问题:控制台日志里的 info、warn 是哪来的?

框架自带的控制台日志提供程序在输出,分类与级别这套机制 2.3 节展开。此刻只需要知道:这些刷屏的行里,"Now listening on" 与请求记录最有观察价值,其余可以暂时当作背景噪声。

本节要点回顾

  • 一条命令装齐全部:SDK 内含运行时、模板、Kestrel,无需另装服务器;
  • 最小应用四步:建主机、组装、登记端点、启动监听,四行代码是第 2 章的引子;
  • 观察哨实验证明管线对每个请求(包括 404)都完整执行,顺序决定可见性;
  • 路径参数在最小 API 里已可用,路由系统的完整版在第 3 章;
  • dotnet watch 是日常开发循环的默认形态。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U