Skip to content

了解 ASP.NET Core 基础知识

ASP.NET Core 项目模板

.NET SDK 包括用于创建 ASP.NET Core 项目和文件的内置模板。 ASP.NET Core 项目模板用于使用必要的文件、文件夹和配置来创建新的 ASP.NET Core 项目,以便高效地搭建并运行项目。

安装 .NET SDK 后,可以在终端或命令提示符中运行 .NET CLI (命令行接口)命令。 若要列出内置模板,请运行 dotnet new list 命令:

sh
$ dotnet new list
这些模板已匹配你的输入:

模板名                                   短名称                      语言        标记
---------------------------------------  --------------------------  ----------  --------------------------
API 控制器                               apicontroller               [C#]        Web/ASP.NET
ASP.NET Core gRPC 服务                   grpc                        [C#]        Web/gRPC/API/Service
ASP.NET Core Web API                     webapi                      [C#],F#     Web/Web API/API/Service
ASP.NET Core Web API (native AOT)        webapiaot                   [C#]        Web/Web API/API/Service
ASP.NET Core Web 应用                    webapp,razor                [C#]        Web/MVC/Razor Pages
ASP.NET Core Web 应用(模型-视图-控制器)  mvc                         [C#],F#     Web/MVC
ASP.NET Core                          web                         [C#],F#     Web/Empty
Blazor Web 应用                          blazor                      [C#]        Web/Blazor/WebAssembly
Blazor WebAssembly 应用                  blazorwasm                  [C#]        Web/Blazor/WebAssembly/PWA
dotnet gitignore 文件                    gitignore,.gitignore                    Config
Dotnet 本地工具清单文件                  tool-manifest                           Config
EditorConfig 文件                        editorconfig,.editorconfig              Config
global.json file                         globaljson,global.json                  Config
MSBuild Directory.Build.props 文件       buildprops                              MSBuild/props
MSBuild Directory.Build.targets 文件     buildtargets                            MSBuild/props
MSTest Playwright Test Project           mstest-playwright           [C#]        Test/MSTest/Playwright
MSTest Test Project                      mstest                      [C#],F#,VB  Test/MSTest
MVC ViewImports                          viewimports                 [C#]        Web/ASP.NET
MVC ViewStart                            viewstart                   [C#]        Web/ASP.NET
MVC 控制器                               mvccontroller               [C#]        Web/ASP.NET
NuGet 配置                               nugetconfig,nuget.config                Config
NUnit 3 Test Item                        nunit-test                  [C#],F#,VB  Test/NUnit
NUnit 3 Test Project                     nunit                       [C#],F#,VB  Test/NUnit
NUnit Playwright Test Project            nunit-playwright            [C#]        Test/NUnit/Playwright
Razor 类库                               razorclasslib               [C#]        Web/Razor/Library
Razor 组件                               razorcomponent              [C#]        Web/ASP.NET
Razor 视图                               view                        [C#]        Web/ASP.NET
Razor 页面                               page                        [C#]        Web/ASP.NET
Web 配置                                 webconfig                               Config
Windows 窗体应用                         winforms                    [C#],VB     Common/WinForms
Windows 窗体控件库                       winformscontrollib          [C#],VB     Common/WinForms
Windows 窗体类库                         winformslib                 [C#],VB     Common/WinForms
WPF 应用程序                             wpf                         [C#],VB     Common/WPF
WPF 用户控件库                           wpfusercontrollib           [C#],VB     Common/WPF
WPF 类库                                 wpflib                      [C#],VB     Common/WPF
WPF 自定义控件库                         wpfcustomcontrollib         [C#],VB     Common/WPF
xUnit Test Project                       xunit                       [C#],F#,VB  Test/xUnit
协议缓冲区文件                           proto                                   Web/gRPC
控制台应用                               console                     [C#],F#,VB  Common/Console
类库                                     classlib                    [C#],F#,VB  Common/Library
解决方案文件                             sln,solution                            Solution
辅助角色服务                             worker                      [C#],F#     Common/Worker/Web

项目模板自定义选项

所有 .NET 项目模板都提供自定义选项,以便根据特定需求定制生成的项目,并使用其他服务对其进行扩展。 例如,可以为数据库访问、身份验证、OpenAPI、缓存、日志记录等添加 Entity Framework Core,使应用程序能够有效地满足特定要求。

若要查看特定模板的所有自定义选项,请使用以下 dotnet new 命令及 --help 选项,并将 <template-name> 替换为你要探索的模板的名称:

sh
$ dotnet new <template-name> --help

使用 .NET CLI dotnet new 命令创建项目

可以使用 dotnet new <template-name> 命令创建新项目。 例如,若要创建新的空白 ASP.NET Core Web 应用项目,可以运行 dotnet new web

创建新的 .NET 项目后,可以使用 dotnet builddotnet run 命令生成并运行项目。

构建你的第一个 ASP.NET Core Web 应用

使用模板创建 ASP.NET Core Web 应用项目

sh
$ dotnet new web -o MyWebApp
已成功创建模板“ASP.NET Core 空”。

正在处理创建后操作...
正在还原 D:\dotnet\MyWebApp\MyWebApp.csproj:
  正在确定要还原的项目…
  已还原 D:\dotnet\MyWebApp\MyWebApp.csproj (用时 83 毫秒)。
已成功还原。

检查项目结构

以下部分概述了空 ASP.NET Core 项目的主要项目文件夹和文件:

MyWebApp.csproj 项目文件

.csproj 项目文件用于:

配置生成项目的方式 指定面向哪个 .NET 版本 管理项目依赖项

obj 文件夹

obj 文件夹包含生成系统使用的中间文件,其中包括从源文件生成的已编译对象文件。 最终生成输出放置在生成过程中创建的 bin 文件夹中。

Properties/launchSettings.json 文件

Properties/launchSettings.json 文件包含有关如何在开发过程中启动应用的配置数据。 这些设置包括 applicationUrl 属性,该属性指定应用使用的根 URL,例如 https://localhost:{port},其中 {port} 是创建项目时分配的随机本地端口号。

launchSettings.json 文件包含以下配置:

json
{
  "$schema": "https://json.schemastore.org/launchsettings.json",
  "profiles": {
    "http": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "http://localhost:5024",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "https": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "https://localhost:7042;http://localhost:5024",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

Program.cs 文件

Program.cs 文件用作 ASP.NET Core 应用的入口点,并具有多个关键用途,其中包括:

主机配置:配置主机,包括设置 Web 服务器。 服务注册:将服务添加到应用的功能,例如数据库上下文、记录和特定框架的专用服务。 中间件管道配置:将应用的请求处理管道定义为一系列中间件实例。 环境配置:为开发、过渡和生产环境设置特定于环境的设置。 在创建的新的空 ASP.NET Core 项目中,Program.cs 文件至少包含以下代码:

c#
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

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

app.Run();

此文件中的以下代码行创建具有预配置默认值的 WebApplicationBuilder,并生成应用:

c#
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet() 方法直接定义处理 HTTP GET 请求的终结点:

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

app.MapGet("/"):定义 HTTP GET 请求的路由。 / 指示此路由响应对应用根 URL 发出的请求。 例如 http://localhost:{port}/,其中 {port} 是项目创建时在 Properties/launchSettings.json 文件中分配的随机分配端口号。

() => "Hello World!":用作请求处理器的 Lambda 表达式。 向根 URL 发出 GET 请求时,将执行此 Lambda 表达式,并返回字符串“Hello World!”

在本地运行 Web 应用

sh
$ dotnet run
正在生成...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5024
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\dotnet\MyWebApp

Web 应用获得服务的方式

生成并运行应用时,将执行以下步骤:

  1. 生成和配置:

调用 MSBuild 以还原依赖项并编译项目。 MSBuild 处理 MyWebApp.csproj 项目文件并将源代码编译为程序集。 应用将读取配置设置,包括为默认启动配置文件(列出的第一个)在 launchSettings.json 中指定的配置设置。

  1. 主机设置:

Program.cs 中的 CreateHostBuilder 方法将设置 Web 主机。 默认情况下,WebHostBuilder 将 Kestrel 配置为 Web 服务器。 Kestrel 是适用于 ASP.NET Core 的跨平台 Web 服务器,专为高性能而设计。 Kestrel 开始侦听已配置 URL 上的传入 HTTP 请求,包括 HTTPS(如果指定)。

  1. 请求处理:

收到请求后,Kestrel 将其转发到 ASP.NET Core 中间件管道。 中间件管道通过一系列中间件组件处理请求,这些组件可以处理身份验证、事件日志和路由等任务。 如果请求与定义的路由匹配,则执行相应的终结点。 在这种情况下,app.MapGet("/", () => "Hello World!") 终结点处理对根 URL 的请求,并返回字符串 Hello World!。

  1. 响应:

响应(在本例中为字符串“Hello World!”)通过中间件管道发送回 Kestrel,然后 Kestrel 将其发送回客户端。

使用 dotnet watch 运行 Web 应用

使用 .NET CLI dotnet watch 命令增强开发工作流。 与命令 dotnet run 不同,每当对源文件进行更改时,dotnet watch 都会自动重新生成并重新运行应用程序。 此外,dotnet watch 还包含热重载功能,该功能会将更新直接注入正在运行的应用程序,而无需重启。 dotnet watch 使你能够更快地查看更改的结果、提高工作效果和效率。

sh
$ dotnet watch
dotnet watch 🔥 Hot reload enabled. For a list of supported edits, see https://aka.ms/dotnet/hot-reload.
  💡 Press "Ctrl + R" to restart.
dotnet watch 🔧 Building...
  正在确定要还原的项目…
  所有项目均是最新的,无法还原。
  MyWebApp -> D:\dotnet\MyWebApp\bin\Debug\net8.0\MyWebApp.dll
dotnet watch 🚀 Started
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5024
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\dotnet\MyWebApp
更改应用的代码并快速查看结果

MyWebApp 应用程序仍在运行,浏览器仍显示 Hello World! 响应:

  1. 在 Visual Studio Code 的“资源管理器”窗格中选择“Program.cs”。
  2. 更改 app.MapGet 方法,使其响应 "Hello .NET Developer Community!" 而不是 "Hello World!"。
  3. 保存对代码所做的更改。

保存更改后,dotnet watch 将自动检测对 Program.cs 文件的修改。 然后,它将:

  • 热重载应用程序:在可能的情况下,dotnet watch 会将更改应用到正在运行的应用程序,而无需完全重新生成。
  • 重新生成应用程序(如有必要):如果无法热重载更改,dotnet watch 会自动重新生成应用程序以合并所做的更改。
  • 重启应用程序(如有必要):如果需要完全重新生成,dotnet watch 会重启应用程序。

终端中的输出指示文件 Program.cs 已更改,并且更改已热重载到正在运行的应用。

若要查看更改的结果,请刷新浏览器。 将显示更新后的响应“Hello .NET Developer Community!”。

通过此自动重新生成和重启过程,可以快速查看更改的结果,而无需手动停止和重启应用程序。

sh
$ dotnet watch
dotnet watch 🔥 Hot reload enabled. For a list of supported edits, see https://aka.ms/dotnet/hot-reload.
  💡 Press "Ctrl + R" to restart.
dotnet watch 🔧 Building...
  正在确定要还原的项目…
  所有项目均是最新的,无法还原。
  MyWebApp -> D:\dotnet\MyWebApp\bin\Debug\net8.0\MyWebApp.dll
dotnet watch 🚀 Started
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5024
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\dotnet\MyWebApp
dotnet watch File changed: .\Program.cs.
dotnet watch 🔥 Hot reload of changes succeeded.
dotnet watch File changed: .\Program.cs.
dotnet watch No hot reload changes to apply.

使用中间件自定义 ASP.NET Core 行为

终端和非终端中间件

每个中间件都可以视为终端或非终端中间件。 非终端中间件会处理请求,然后调用管道中的下一个中间件。 终端中间件是管道中的最后一个中间件,没有下一个要调用的中间件。

使用 app.Use() 添加的委托可以是终端或非终端中间件。 这些委托需要一个 HttpContext 对象和一个 RequestDelegate 对象作为参数。 通常情况下,委托包括 await next.Invoke();。 这会将控制权传递给管道上的下一个中间件。 该行之前的代码在下一个中间件之前运行,该行之后的代码在下一个中间件之后运行。 使用 app.Use() 添加的委托在响应发送到客户端之前有两次机会对请求采取行动;一次是在终端中间件生成响应之前,另一次是在终端中间件生成响应之后。

使用 app.Run() 添加的委托始终是终端中间件。 不会调用管道中的下一个中间件。 是运行的最后一个中间件组件。 只需要 HttpContext 对象作为参数。 app.Run() 是添加终端中间件的快捷方式。

c#
app.Use(async (context, next) =>
{
    await context.Response.WriteAsync("Hello from middleware 1. Passing to the next middleware!\r\n");

    // Call the next middleware in the pipeline
    await next.Invoke();

    await context.Response.WriteAsync("Hello from middleware 1 again!\r\n");
});

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from middleware 2!\r\n");
});

使用内置中间件

c#
app.MapGet("/about", () => "helloworld.study");
app.UseRewriter(new RewriteOptions().AddRedirect("history", "about"));

此代码添加 URL 重写程序中间件组件,该组件用于将请求从 /history 重定向到 /about。 AddRedirect() 方法采用两个参数:用于匹配请求路径的正则表达式模式,以及要重定向到的替换路径。

创建自定义中间件

对于每个请求,它应记录请求方法、路径和响应状态代码。 紧接在 app.Run() 之前,插入以下代码:

c#
app.Use(async (context, next) =>
{
    Console.WriteLine($"{context.Request.Method} {context.Request.Path} {context.Response.StatusCode}");
    await next();
});

在上述代码中:

app.Use() 向管道添加一个自定义中间件组件。 该组件采用一个 HttpContext 对象和一个 RequestDelegate 对象作为参数。 delegate 将请求方法、路径和响应状态代码写入到控制台。 await next() 调用管道中的下一个中间件组件。

更改中间件的顺序

应用似乎正常工作,但存在问题。 你请求了 /history 页,但控制台输出没有显示它。 之所以发生此行为,是因为用于记录请求详细信息的自定义中间件组件是在 URL 重写器中间件之后添加的。 URL 重写器中间件将请求从 /history 重定向到 /about 并发送响应,自定义中间件组件看不到请求。 让我们来解决此问题。

将你添加的 app.Use() 行移动到 app.UseRewriter() 行的正前方。

c#
app.Use(async (context, next) =>
{
    Console.WriteLine($"{context.Request.Method} {context.Request.Path} {context.Response.StatusCode}");
    await next();
});

app.MapGet("/", () => "Hello .NET Developer Community!");
app.UseRewriter(new RewriteOptions().AddRedirect("hello", "/"));

app.MapGet("/about", () => "helloworld.study");
app.UseRewriter(new RewriteOptions().AddRedirect("history", "about"));

修复状态代码

该应用几乎已准备就绪,但还有一个问题。 控制台输出中的状态代码始终为 200,即使应用重定向了请求也是如此。 /history 请求的状态代码应为 302 重定向。 发生此行为是因为处理中间件组件的顺序存在另一个问题。

自定义中间件组件将详细信息记录到控制台,然后调用 await next() 来传递给下一个中间件组件。 问题是,StatusCode 对象的 Response 属性是在终端中间件组件启动响应后设置的。 让我们更改代码以修复此问题。

在你添加的委托中,将 Console.WriteLine() 行移动到 await next() 行之后。

c#
app.Use(async (context, next) =>
{
    await next();
    Console.WriteLine($"{context.Request.Method} {context.Request.Path} {context.Response.StatusCode}");
});

在 ASP.NET Core 中使用依赖项注入配置服务

注册和使用服务

创建服务

c#
using System;

namespace MyWebApp.Services;

public class WelcomeService
{
    DateTime _currtentTime;
    Guid _serviceId;

    public WelcomeService()
    {
        _serviceCreated = DateTime.Now;
        _serviceId = Guid.NewGuid();
    }

    public string GetWelcomeMessage()
    {
        return $"Welcome to helloworld.study! The current time is {_serviceCreated}. This service instance has an ID of {_serviceId}";
    }
}

注册该服务

  1. 打开 Program.cs 文件。

  2. 将下面的指令添加到文件的顶部:

c#
using MyWebApp.Services;

此指令解析对 WelcomeService 类的引用。

  1. 紧接在 var builder = WebApplication.CreateBuilder(args); 行之后,添加以下代码:
c#
builder.Services.AddSingleton<WelcomeService>();

WebApplication.CreateBuilder 创建名为 WebApplicationBuilderbuilder 类的新实例。 前面的代码使用单一实例生存期向服务容器注册 WelcomeService 类。

  1. app.MapGet("/", () => "Hello World!"); 行更改为以下代码:
c#
app.MapGet("/", (WelcomeService welcomeService) => welcomeService.GetWelcomeMessage());

此代码将 HTTP GET 请求映射到根 URL (/),指向一个委托,该委托返回由 WelcomeService 服务生成的欢迎消息。

Program.cs 文件应如下所示:

c#
using MyWebApp.Services;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<WelcomeService>();

var app = builder.Build();

app.MapGet("/", (WelcomeService welcomeService) => welcomeService.GetWelcomeMessage());

app.Run();

使用接口注册服务

c#
using System;

namespace MyWebApp.Interfaces;

public interface IWelcomeService
{
    string WelcomeService();
}
  1. 更新 WelcomeService 类声明以实现 IWelcomeService 接口:
c#
public class WelcomeService : IWelcomeService
  1. 打开 Program.cs 文件。将 builder.Services.AddSingleton<WelcomeService>(); 行更新为以下代码:
c#
builder.Services.AddSingleton<IWelcomeService, WelcomeService>();
  1. app.MapGet("/", (WelcomeService welcomeService) => welcomeService.GetWelcomeMessage()); 行更新为以下代码:
c#
app.MapGet("/", (IWelcomeService welcomeService) => welcomeService.GetWelcomeMessage());

匿名函数现在需要 IWelcomeService 而不是 WelcomeService

Program.cs 文件应如下所示:

c#
using MyWebApp.Services;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<WelcomeService>();

var app = builder.Build();

app.MapGet("/", (WelcomeService welcomeService) => welcomeService.GetWelcomeMessage());

app.Run();

服务生存期

注册服务时,必须选择与在应用中使用服务的方式匹配的生存期。 生存期会影响服务在注入组件时的行为方式。 到目前为止,你已使用 AddSingleton 方法注册了服务。 此方法使用单一实例生存期注册服务。 ASP.NET Core 中的服务有三种内置生存期:

  • 单一实例
  • 范围性
  • 暂时性

单一实例生存期

使用单一实例生存期注册的服务会在应用启动时创建一次,并在应用的生存期内重复使用。 这种生存期对于创建成本高昂或不会经常更改的服务非常有用。 例如,如果一个服务可以从文件中读取配置设置,则可以注册为单一实例。

请使用 AddSingleton 方法将单一实例服务添加到服务容器。

作用域生存期

使用作用域生存期注册的服务会在配置的每个范围内创建一次,ASP.NET Core 会为每个请求设置该范围。 ASP.NET Core 中的作用域服务通常在收到请求时创建,并在请求完成时处理掉。 如果服务需要访问特定于请求的数据,这种生存期会非常有用。 例如,从数据库中提取客户数据的服务可以注册为作用域服务。

请使用 AddScoped 方法将范围性服务添加到服务容器。

暂时性生存期

使用暂时性生存期注册的服务会在每次请求时创建。 这种生存期适用于轻型无状态服务。 例如,执行专用计算的服务可以注册为暂时性服务。

请使用 AddTransient 方法将暂时性服务添加到服务容器。

探索服务生存期

测试单一实例服务生存期

  1. 如果之前的练习中已经运行了应用,那么它应当仍在运行。 如果没有如期运行,请按照之前的方式运行应用。

  2. 刷新浏览器窗口并留意欢迎消息中显示的时间。

  3. 等待几秒钟,然后再次刷新浏览器窗口。 欢迎消息没有变化。 时间戳和 GUID 保持不变。

欢迎消息中显示的时间和 GUID 没有变化,因为 WelcomeService 服务注册为单一实例服务。 在应用启动时创建一次服务,并在应用的生存期内重复使用。 每个客户端的每个请求都使用相同的服务实例。 不会创建其他服务实例。

  1. 通过在 Visual Studio Code 中按 Shift+F5 来停止应用。

测试作用域服务生存期

要了解作用域服务生存期,需要更改注册 WelcomeService 服务的方式。

  1. 在 Program.cs 文件中,更改 WelcomeService 服务的注册以使用作用域服务生存期:
c#
builder.Services.AddScoped<IWelcomeService, WelcomeService>();

此代码将 WelcomeService 类注册到具有作用域生存期的服务容器。

  1. 请按照之前的方式运行应用。

  2. 请留意欢迎消息中显示的时间和 GUID。 刷新浏览器窗口并注意每次时间都会变化,GUID 也是不同的。

欢迎消息中显示的数据会变化,因为 WelcomeService 服务现已注册为作用域服务。 每个客户端请求都会单独创建一次服务,请求完成后,该服务就会被释放。 每个客户端的每个请求都使用新的服务实例。

  1. 通过在 Visual Studio Code 中按 Shift+F5 来停止应用。

  2. 让我们来探讨一下,在同一个请求中尝试使用同一 WelcomeService 服务的两个实例时,作用域服务生存期的行为。 将 app.MapGet() 行更改为以下代码:

c#
app.MapGet("/", async (IWelcomeService welcomeService1, IWelcomeService welcomeService2) => 
    {
        string message1 = $"Message1: {welcomeService1.GetWelcomeMessage()}";
        string message2 = $"Message2: {welcomeService2.GetWelcomeMessage()}";
        return $"{message1}\n{message2}";
    });

在上述代码中:

  • app.MapGet() 委托现在有两个类型均为 IWelcomeService 的参数。 委托会生成两条欢迎消息,每个服务实例各一条。
  • 委托在单个响应中返回这两条消息。
  1. 请按照之前的方式运行应用。 请注意,即使两条欢迎消息是在不同时间生成的,并且它们是作为单独的参数传递给委托的,但消息内容是相同的。

此行为是因为 WelcomeService 服务注册为作用域服务。 该服务是针对每个客户端请求单独创建的,在同一个请求中,所有需要它的组件都会获得同一个实例。 welcomeService1welcomeService2 都引用 WelcomeService 服务的同一实例。

  1. 多次刷新页面。 请注意,欢迎消息中的时间戳和 GUID 每次都会变化,但两条消息始终相同。

  2. 通过在 Visual Studio Code 中按 Shift+F5 来停止应用。

测试暂时性服务生存期

现在,让我们检查暂时性服务生存期。

  1. 更改 WelcomeService 服务的注册以使用暂时性服务生存期:
c#
builder.Services.AddTransient<IWelcomeService, WelcomeService>();

此代码将 WelcomeService 类注册到具有暂时性生存期的服务容器。

  1. 请按照之前的方式运行应用。 这两条消息中的时间保持不变,因为 WelcomeService 服务的两个实例是同时创建的。 但是,每个消息中的 GUID 不同,因为每个服务实例都是唯一的。

此行为代表暂时性服务生存期。 每次将服务注入组件时,都会创建新的服务实例。 由于它注入到委托中两次,因此会创建两个服务实例。

  1. 多次刷新页面。 每次刷新页面时,两个消息中的时间戳始终相同,但每个消息中的 GUID 不同。

  2. 通过在 Visual Studio Code 中按 Shift+F5 来停止应用。

发布 ASP.NET Core 应用

为依赖于框架的部署进行发布

依赖框架的部署是 ASP.NET Core 应用的默认部署。 发布依赖于框架的应用时,部署包中仅包含应用的文件和依赖项。 不包括 .NET 运行时。 目标计算机必须安装正确的 .NET 运行时版本才能运行应用。

c#
$ dotnet publish
  正在确定要还原的项目…
  所有项目均是最新的,无法还原。
[D:\dotnet-training\MyWebApp\MyWebApp.csproj]       
  MyWebApp -> D:\dotnet-training\MyWebApp\bin\Release\net8.0\MyWebApp.dll
  MyWebApp -> D:\dotnet-training\MyWebApp\bin\Release\net8.0\publish\
$ cd .\bin\Release\net8.0\
$ dotnet .\MyWebApp.dll
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\dotnet-training\MyWebApp\bin\Release\net8.0

为独立部署进行发布

独立部署包括应用及其依赖项以及 .NET 运行时。 由于应用包含 .NET 运行时,因此目标计算机不需要安装 .NET 运行时才能运行应用。 这使得独立部署大于依赖于框架的部署。 独立应用还必须处理 .NET 运行时更新的部署,以接收最新修补程序。

运行以下命令,针对 64 位 Windows 将应用发布为独立部署:

c#
$ dotnet publish -r win-x64 --self-contained
  正在确定要还原的项目…
  已还原 D:\dotnet-training\MyWebApp\MyWebApp.csproj (用时 11.05 秒)。
 [D:\dotnet-training\MyWebApp\MyWebApp.csproj]       
  MyWebApp -> D:\dotnet-training\MyWebApp\bin\Release\net8.0\win-x64\MyWebApp.dll
  MyWebApp -> D:\dotnet-training\MyWebApp\bin\Release\net8.0\win-x64\publish\
$ cd .\bin\Release\net8.0\win-x64\
$ dotnet .\MyWebApp.dll
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: D:\dotnet-training\MyWebApp\bin\Release\net8.0\win-x64

Last updated:

Released under the MIT License.