WebAppliction

用途:是实际运行的ASP.NET Core应用实例。通过它我们可以注册中间件[Use()]映射终节点[Map()]最终调用[Run()]启动服务监视器

类比:真正盖好并运行的房子,住人、供电、供水的阶段。

核心组成

1
2
3
4
5
6
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();
成员 类型 说明
app.UseXxx() 中间件添加方法 用于处理请求的中间件管道
apapp.UseXxx() 终结点注册 定义请求的路由逻辑
app.Run() 启动方法 启动HTTP服务监听请求
app.Environment IHostEnvironment 当前环境
app.Services IServiceProvider 访问服务容器中的服务

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
app.Map("/test", async (pipeBuilder) =>
{
pipeBuilder.Use(async (context, next) =>
{
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("1 start<br/>");
await next.Invoke();
await context.Response.WriteAsync("1 end<br/>");
});
pipeBuilder.Use(async (context, next) =>
{
await context.Response.WriteAsync("2 start<br/>");
await next.Invoke();
await context.Response.WriteAsync("2 end<br/>");
});
pipeBuilder.UseMiddleware<TestIMddleware>();
pipeBuilder.Run(async context =>
{
await context.Response.WriteAsync("Run<br/>");
dynamic obj = context.Items["BodyJson"];
if(obj != null)
{
await context.Response.WriteAsync($"BodyJson: {obj}<br/>");
}
});
pipeBuilder.Run(async context =>
{
await context.Response.WriteAsync("Run<br/>");
});
});
  1. app.Map(“/test”, async (pipeBuilder) => { … })
    这里将/test路径映射到一个新的中间件分支中。
    Map()是条件分支(类似if),只当路径以/test开头时才执行内部管道。
    pipeBuilder就是新的IApplicationBuilder,你可以在里面Use、Run中间件,彼此不会影响主管道。

  2. context.Response.ContentType = “text/html”;
    context.Response是Httponse对象,代表服务器要发回的响应。
    ContentType是设置响应头Content-Type.
    设置为“text/html”,意味着:浏览器将按HTML格式渲染内容。写入的字符串将被当作HTML解析,而不是普通文本。
    next.Invoke();进入下一个中间件

常见 Content-Type 类型

ContentType 说明

text/html 返回 HTML 网页内容
text/plain 纯文本(无格式)
application/json JSON 数据(常用于 API)
application/xml XML 数据
text/css CSS 样式表
application/javascript JavaScript 脚本

如果没设置 ContentType,默认是 text/plain,浏览器不会解析为 HTML,而是直接把 <h1>Hello</h1> 当作纯文本显示。

3.pipeBuilder.UseMiddleware<TestIMddleware>();自定义中间件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TestIMddleware
{
private readonly RequestDelegate next;
public TestIMddleware(RequestDelegate next)
{
this.next = next;
}
public async Task InvokeAsync(HttpContext context)
{
await context.Response.WriteAsync("TestIMddleware start<br/>");
await next.Invoke(context);
await context.Response.WriteAsync("TestIMddleware end<br/>");
}
}
  1. 为什么第二个Run()不执行?
    中间件管道是单挑链表结构,从上到下依次调用。
    Run()相当于Use()的最后一环,他不会调用next(),所以执行到第一个Run()后,后面的中间件被跳过了。
    规则:只能有一个Run(),如果写多了,只有第一个生效,其他被忽略。

WebApplicationBuilder

用途:WebApplicationBuilder是用于构建WebApplication的工厂类,她负责配置服务、配置应用环境、日志、配置文件、主机设置等内容。

类比:他是建房子的阶段:备材料、设计圈、准备工人。

核心组成

1
var builder = WebApplication.CreateBuilder(args);
成员 类型 说明
builder.Services IServiceCollection 注册DI容器中的服务
builder.Configuration ICongiguration 加载配置文件(appsettings.json、环境变量等)
builder.Logging ILoggingBuilder 配置日志
builder.Environment IHostEnvironment 当前运行环境(开发、生产)
builder.Host IHostBuilder 配置主机设置,如添加 HostedService
builder.WebHost IWebHostBuilder 主要配置 WebServer(Kestrel)、监听端口等

示例

1
2
3
4
5
6
7
8
9
10
var builder = WebApplication.CreateBuilder(args);

// 配置服务
builder.Services.AddControllers();
builder.Services.AddDbContext<AppDbContext>();
builder.Services.AddSwaggerGen();

// 配置日志
builder.Logging.ClearProviders();
builder.Logging.AddConsole();

AddControllers();配置服务(注册到 DI 容器)

AddDbContext<AppDbContext>();注册你的数据库上下文 AppDbContext。
通常你会配合指定数据库类型,例如:

1
2
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("Default")));

AddSwaggerGen();注册 Swagger 文档生成器,用于自动生成 OpenAPI 接口文档。
会启用 /swagger/v1/swagger.json 及 /swagger 的 UI 页面。
配合 app.UseSwagger() 和 app.UseSwaggerUI() 使用。

Logging.ClearProviders()清除所有默认注册的日志记录器(例如 Debug、EventLog 等)。
AddConsole() 启用控制台日志输出(运行时输出到终端)。

底层机制

  1. WebApplicationBuilder 是对 HostApplicationBuilder 的包装,提供默认配置,并集成 IHostBuilder 和 IWebHostBuilder。

  2. WebApplication 实现了 IApplicationBuilder 接口,是一个扩展了 Web 中间件构建和执行的类型。

  3. 构建过程本质上还是走 Host.CreateDefaultBuilder(),再添加了 Kestrel、日志、配置等默认配置。