第4章 .NET 8.0 ASP.NET Core图书管理系统 :项目布局

第1章 框架学习的基石与实战策略

第2章 大话ASP.NET Core 入门

第3章 创建最小(Minimal APIs)API应用程序

第4章 .NET 8.0 ASP.NET Core图书管理系统 :项目布局

在第3章中,我们利用ASP.NET Core的“空”模板创建了BookQuerySystem应用程序。这个模板为我们提供了一个简洁的基础架构,使得项目布局清晰易懂。首次运行并看到"Hello World"的那一刻,的确令人印象深刻。现在,让我们一起探讨一下这个项目的布局,了解其主要的文件和文件夹。
在这里插入图片描述
按"F5",你会看到"Hello World"的简单响应,这表明应用程序已经正确配置和运行。这个简洁的项目结构为后续添加功能和扩展提供了便利,无论是添加数据库连接、路由映射还是自定义中间件,都能轻松应对。
在这里插入图片描述

4.1.Program.cs文件

Program.cs文件是ASP.NET Core应用程序的入口文件,也是配置服务和中间件的主要场所。对于我们的BookQuerySystem图书管理系统应用程序,我们将在此文件中进行更多的配置和扩展,以满足应用程序的需求。

2021年前我写了一篇.NET 6.0 MVC图书查询系统的教程,由于.NET 6.0远远不如.NET8.0好用,所以那篇.NET6.0的教程1到现在还没更完!!! :)

4.1.1 入口点方法

在传统的 C# 程序中(C# 9 之前),Main 方法是程序的入口点。当你运行一个程序时, 运行时 2 (runtime)会查找 Main 方法并从那里开始执行代码。

然而,在使用顶级语句时,你不再显式定义 Main 方法。相反, 编译器3 会为你自动生成一个包含所有顶级语句的 Program 类和一个入口点方法。这个自动生成的方法充当程序的入口点,它的名称不再是 Main,而是一个由编译器生成的内部名称,你的代码无法直接引用这个名称。

4.1.2 顶级语句的工作原理

当你使用顶级语句编写程序时,编译器会将你的代码包装在一个自动生成的 Program 类中,并创建一个入口点方法(不是 Main),然后在这个方法内部执行你的顶级语句。这样,你就可以直接编写逻辑代码,而无需关心类的定义或 Main 方法的创建。

使用顶级语句的 C# 程序

Console.WriteLine("Hello World!");

编译器会将这段代码转换为类似于以下的形式:

class Program  
{  static void <GeneratedEntryPointMethodName>()  {  Console.WriteLine("Hello World!");  }  
}

< GeneratedEntryPointMethodName > 是一个由编译器生成的名称,它充当程序的入口点。

4.1.3 传统C#编写的程序入口点在.NET平台的结构

在传统C#编写的程序中,入口点通常是Program类中的Main方法定义的。

using System; 
namespace BookQuerySystem
{ public class Program { public static void Main(string[] args) { Console.WriteLine("Hello World!"); } } 
}

Main方法中的args参数是一个字符串数组,它包含了传递给程序的命令行参数。这个args参数是由运行时环境提供的,它在程序的Main方法中可用。

命令行参数是指在操作系统命令行界面(如Windows的CMD或Linux的终端)中启动一个程序时,跟在程序名后面的额外信息。这些信息通常是以空格分隔的字符串,它们可以提供程序运行时的配置选项、文件路径或其他必要的数据。

这些参数通过Main方法的string[] args参数传递给程序。例如,如果你在命令行中运行以下命令:

BookQuerySystem.exe -input data.txt -verbose

这里,BookQuerySystem.exe是程序的名称,(-input ) ( data.txt)(-verbose)是命令行参数。在程序的Main方法中,args数组会包含这些参数:

public static void Main(string[] args)
{Console.WriteLine(args[0]); // 输出 "-input"Console.WriteLine(args[1]); // 输出 "data.txt"Console.WriteLine(args[2]); // 输出 "-verbose"    
}

程序可以解析这些参数以决定执行什么操作,例如,-input用于指定要处理的文件,-verbose用于开启详细输出模式。在实际应用中,通常会使用条件语句或第三方库来解析和处理这些参数。

在顶级语句的上下文中,你可以直接访问它,因为编译器会自动为你处理所有的细节。
例如:

Console.WriteLine(args[0]); // 输出 "-input"
Console.WriteLine(args[1]); // 输出 "data.txt"
Console.WriteLine(args[2]); // 输出 "-verbose"
4.1.4在一个.NET应用程序中,只能有一个入口点

这通常对应于一个包含Main方法的文件。在引入顶级语句后,虽然不再需要显式声明Main方法,但这个限制仍然存在。这意味着在一个项目中,只能有一个包含顶级语句的源代码文件(通常是Program.cs或类似命名的文件),这个文件将会成为程序的入口点,编译器会自动处理顶级语句并生成内部的Main方法。

4.1.5 顶级语句与命名空间:在 ASP.NET Core 中使用最小API模式

顶级语句允许你在没有显式包含在任何特定命名空间中的情况下编写代码。这些语句默认处于全局命名空间中,特别适用于 ASP.NET Core等框架中的简单应用程序和最小API模式。

顶级语句与全局命名空间

顶级语句是不被任何类、结构或命名空间包围的代码行。在使用 ASP.NET Core 创建 Web 应用程序时,你通常会看到这样的顶级语句,它们用于配置和启动应用程序。

例如第3章中通过ASP.NET Core 空”模板创建的BookQuerySystem应用程序,目前你可以在Program.cs文件中看到四行代码(这四行代码在第3章已详细讲解):

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();app.MapGet("/", () => "Hello World!");app.Run();

这些代码中的每一行都是一个顶级语句,它们共同构成了应用程序的入口点。由于这些语句没有包含在任何命名空间内,因此它们属于全局命名空间

结合使用顶级语句与命名空间

虽然顶级语句通常用于全局命名空间中的简单配置,但你也可以在相同的文件中定义命名空间和类型。这允许你将相关的数据和逻辑组织在一起,同时保持顶级语句的简洁性。

例如,你可以在全局命名空间中使用顶级语句来配置应用程序和定义数据模型,并在一个单独的命名空间中定义视图模型。

// 顶级语句,全局命名空间
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();app.MapGet("/", () => "Hello World!");app.Run();// 数据模型,全局命名空间
public class Book
{public int Id { get; set; }public string Title { get; set; }public string Classification { get; set; }public string Author { get; set; }public DateTime PublicationDate { get; set; }public decimal Price { get; set; }
}// 视图模型,特定命名空间
namespace BookQuerySystem.ViewModels
{public class BookClassificationViewModel{public List<Book>? Books { get; set; }public SelectList? Classifications { get; set; }public string? BookClassification { get; set; }public string? Search { get; set; }}
}

顶级语句通常用于非常简单的程序或配置,而在实际的应用程序开发中,仍然推荐将逻辑组织在适当的文件和命名空间中,因此不建议将如下代码放在Program.cs文件中:

// 视图模型,特定命名空间
namespace BookQuerySystem.ViewModels
{public class BookClassificationViewModel{public List<Book>? Books { get; set; }public SelectList? Classifications { get; set; }public string? BookClassification { get; set; }public string? Search { get; set; }}
}

你应该将视图模型放在专门的文件夹和命名空间中,例如创建一个 ViewModels 文件夹,并在其中创建一个名为 BookClassificationViewModel.cs 的文件,类名有点长!好在易懂,请不要着急,至于这个类是用来做什么的,我们以后早晚会讲到。

最小API模式

在 ASP.NET Core 中,最小API模式利用顶级语句和全局命名空间来创建简洁的 HTTP API/Web API。这种模式特别适用于微服务架构和需要快速开发的场景。

通过结合使用顶级语句和命名空间,你可以:

  • 保持代码的简洁性和可读性。
  • 快速定义和实现 Web API 端点。
  • 将相关数据和逻辑组织在命名空间中,以便于维护和扩展。

顶级语句和命名空间提供了灵活的方式来组织代码。在 ASP.NET Core 框架中,合理利用这些特性可以帮助你创建简洁、高效且易于维护的应用程序。尽管顶级语句很方便,但合理使用命名空间仍然是组织代码和避免命名冲突的重要策略。

4.2 appsettings.json文件

appsettings.json 文件在 ASP.NET Core 应用程序中扮演着重要的角色,它用于存储应用程序的配置设置。这些设置可以包括数据库连接字符串、日志级别、外部服务的 API 密钥等。在 BookQuerySystem 应用程序中,appsettings.json 文件同样被用来定义应用程序的一些基础配置。

下面是对 BookQuerySystem 应用程序中 appsettings.json`文件的详细解释:

{"Logging": {"LogLevel": {"Default": "Information","Microsoft.AspNetCore": "Warning"}},"AllowedHosts": "*"
}
  1. Logging:

    • LogLevel: 这个部分定义了应用程序的日志级别。日志级别决定了应用程序将记录哪些级别的日志信息。
      • Default: “Information” 表示默认情况下,应用程序将记录所有级别为“Information”及以上的日志信息(即 Information、Warning、Error、Critical)。
      • Microsoft.AspNetCore: “Warning” 表示对于 Microsoft.AspNetCore 命名空间下的日志,只记录级别为“Warning”及以上的日志信息。(级别越往下越详细
  2. AllowedHosts:

    • " * “: 这个设置定义了应用程序可以接受的主机头(Host Header)。” * " 表示应用程序可以接受来自任何主机头的请求。在生产环境中,你应该将这个设置限制为你的应用程序实际部署的主机名,以增强安全性。
4.2.1 如何使用 appsettings.json
  1. 创建和配置 appsettings.json:

    • 在你的 ASP.NET Core 项目中,确保有一个 appsettings.json文件。
    • 在文件中添加你需要的配置设置,比如日志级别、数据库连接字符串等。
  2. 读取配置:

    • 在你的应用程序中,你可以使用 IConfiguration接口来读取 appsettings.json文件中的配置设置。
    • 例如,在 Program.cs 文件中,你可以通过依赖注入来获取 IConfiguration 实例,并使用它来读取配置值。
  3. 环境特定的配置:

    • 你可以创建环境特定的配置文件,如 appsettings.Development.json 和 appsettings.Production.json,来存储不同环境下的配置设置。
    • ASP.NET Core 会根据当前的环境变量自动选择正确的配置文件。
  4. 保护敏感配置:

    • 对于包含敏感信息的配置设置,如数据库密码或 API 密钥,你应该使用安全的存储机制,如 Azure Key Vault 或环境变量。
    • 避免在 appsettings.json 文件中直接存储敏感信息。
4.2.2 依赖注入

在 ASP.NET Core 应用程序中,依赖注入(DI)是一种核心的设计模式,它允许你在运行时将依赖项(如服务、配置等)自动传入到类中。IConfiguration 是一个用于访问应用程序配置设置的接口,通常这些设置存储在 appsettings.json 文件中。

在 Program.cs 文件中, ASP.NET Core 的框架已经完成了大部分工作,当你调用 WebApplication.CreateBuilder(args) 方法时,它会自动配置 IConfiguration 和其他基础服务(他们都是框架内置的,开发者无须手动管理和初始化)。

要在代码中使用 IConfiguration,你只需要在需要它的类中添加一个构造函数参数,或直接在路由处理程序(即 lambda 表达式或委托)中注入IConfiguration服务 。ASP.NET Core 的依赖注入系统就会自动为你提供 IConfiguration 的实例

下面是一个更简单的例子,展示了如何在 ASP.NET Core 最小 API 中使用依赖注入来获取 IConfiguration 实例,并读取配置文件中的一个简单设置。

修改 appsettings.json 文件如下:

{  "BookQuerySystemSettings": {  "Greeting": "Hello from configuration!"  },  "Logging": {  "LogLevel": {  "Default": "Information",  "Microsoft.AspNetCore": "Warning"  }  },  "AllowedHosts": "*"  
}

然后在 Program.cs 文件中这样使用依赖注入来获取 IConfiguration 并读取 “BookQuerySystemSettings:Greeting” 的值:

using System.ComponentModel.DataAnnotations;var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();// 使用依赖注入获取 IConfiguration 实例,并读取 Greeting 设置  
app.MapGet("/greeting", (IConfiguration config) =>  
{  // 读取 BookQuerySystemSettings:Greeting 设置  var greeting = config["BookQuerySystemSettings:Greeting"];  return greeting ?? "Greeting not found";  
}); app.MapGet("/", () => "Hello World!");app.Run();public class Book
{public int Id { get; set; }public string Title { get; set; }public string Classification { get; set; }public string Author { get; set; }public DateTime PublicationDate { get; set; }public decimal Price { get; set; }
}

在这个例子中,我们定义了一个 /greeting 路由,它的处理程序接受一个 IConfiguration 参数。ASP.NET Core 的依赖注入系统会在运行时自动注入这个参数的一个实例。然后,我们使用索引器 config[“BookQuerySystemSettings:Greeting”] 来读取 “BookQuerySystemSettings:Greeting” 配置项的值,并将其作为响应返回。

如果你访问 /greeting 路由,你将看到从 appsettings.json 文件中读取的 “Hello from configuration!” 消息。如果你访问根路径 /,你将看到默认的 “Hello World!” 消息。

按"F5",你会看到"Hello World"的简单响应
在这里插入图片描述
在浏览器中访问https://localhost:7260/greeting你会看到下图:
在这里插入图片描述
前面说过我们定义了一个 /greeting 路由,它的处理程序接受一个 IConfiguration 参数。简单来说就是 /greeting 路由是通过app.MapGet(“/greeting”, (IConfiguration config) => {…})定义的。当你在浏览器中访问https://localhost:7260/greeting时,这个 URL4 会触发定义好的处理程序,即传入IConfiguration实例的lambda表达式。

该处理程序会读取配置中的BookQuerySystemSettings:Greeting键的值,并将其返回作为HTTP响应。如果找不到该配置键,它会返回一个默认的字符串“Greeting not found”。

注意,实际的端口号7260是随机的,会根据你的应用程序配置和本地设置有所不同。当你启动一个ASP.NET Core应用时,控制台会输出实际监听的URL,包括端口号。确保使用正确的端口号来访问你自己的应用程序。

4.3 launchSettings.json文件

在 ASP.NET Core 项目中,launchSettings.json文件扮演着至关重要的角色,它详细定义了应用程序在开发环境下的启动配置。这个文件位于项目的 Properties文件夹内。通过精心配置这个文件,你可以轻松地控制应用程序的运行方式,包括它监听的端口号、是否启用 SSL 加密、以及环境变量的设置等。

launchSettings.json文件中的配置只在开发环境中有效。当应用程序部署到生产环境时,通常会使用不同的配置来源,比如appsettings.jsonappsettings.{Environment}.json文件,以及环境变量或配置服务器。生产环境的配置不会受到launchSettings.json的影响,除非你特别将这些设置迁移到生产环境中。

常见托管环境:

  1. 开发环境(Development Environment)

    • 开发环境是程序员编写和测试代码的地方。在这里,开发者可以自由地实验、调试和修复错误,而不必考虑性能优化或安全性。launchSettings.json文件中的配置就是针对这种环境的,它允许开发者快速启动应用并进行调试,比如设置特定的端口、启用详细日志等。
    • 在开发环境中,为了方便调试,通常会使用更宽松的安全策略和显示详细的错误信息。
  2. 预生产环境(Staging or Pre-Production Environment)

    • 预生产环境是部署新代码或应用更新前的最后一步,它用于模拟生产环境,但不对外公开。这个环境用于验证新功能、性能优化和最终的用户验收测试。预生产环境的配置通常与生产环境一致,以便于发现问题并解决。
  3. 生产环境(Production Environment)

    • 生产环境是应用正式对外提供服务的环境。这里的配置需要考虑性能、安全性和稳定性。应用程序在生产环境中通常部署在高可用的服务器集群上,以确保服务的连续性和可靠性。
    • 生产环境的配置通常来自appsettings.json文件,以及appsettings.Production.json(或其他特定环境的文件,如appsettings.Staging.json)。这些文件包含了生产环境中应用需要的配置,如数据库连接字符串、API密钥、服务端口等。
    • 生产环境还会使用环境变量来存储敏感信息,如API密钥或数据库密码,这样可以避免把这些信息直接写入代码或配置文件中,提高安全性。
    • 此外,生产环境可能还使用配置服务器(如Azure App Configuration或Consul)来集中管理配置,这有助于动态更新配置,而无需重新部署应用。
4.3.1 launchSettings.json 文件结构
{"$schema": "http://json.schemastore.org/launchsettings.json","iisSettings": {"windowsAuthentication": false,"anonymousAuthentication": true,"iisExpress": {"applicationUrl": "http://localhost:64271","sslPort": 44318}},"profiles": {"http": {"commandName": "Project","dotnetRunMessages": true,"launchBrowser": true,"applicationUrl": "http://localhost:5035","environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development"}},"https": {"commandName": "Project","dotnetRunMessages": true,"launchBrowser": true,"applicationUrl": "https://localhost:7260;http://localhost:5035","environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development"}},"IIS Express": {"commandName": "IISExpress","launchBrowser": true,"environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development"}}}
}

launchSettings.json文件的结构清晰明了,主要包含以下几个核心部分:

  1. $schema

    • 这是一个指向 JSON 模式文件的 URL,它用于验证 launchSettings.json文件的格式是否正确。
    • 借助这个模式文件,你可以确保你的配置文件符合预期的格式规范。
  2. iisSettings

    • 这部分专门用于配置 IIS Express 的相关参数。
    • windowsAuthentication:一个布尔值,用于指定是否启用 Windows 身份验证机制。
    • anonymousAuthentication:同样是一个布尔值,用于控制是否允许匿名访问。
    • iisExpress:这是一个嵌套的对象,它进一步定义了 IIS Express 的具体设置,如应用程序的 URL 和 SSL 端口号等。
  3. profiles

    • 这是 launchSettings.json 文件中最关键的部分,它包含了多个启动配置,每个配置都对应着应用程序的一种启动方式。
    • 常见的配置有 http、https 和 IIS Express,它们分别定义了应用程序在 HTTP 协议、HTTPS 协议以及 IIS Express 上的启动行为。
4.3.2 profiles 部分详解

profiles 部分是 launchSettings.json 文件的核心,它包含了多个启动配置,每个配置都详细定义了应用程序的启动参数。

  • http 配置

    • commandName:指定了启动命令,对于 ASP.NET Core 应用程序来说,通常是 “Project”。
    • dotnetRunMessages:一个布尔值,用于控制是否在控制台输出 dotnet 运行时的消息。
    • launchBrowser:另一个布尔值,用于指定是否在应用程序启动时自动打开浏览器并导航到应用程序的 URL。
    • applicationUrl:定义了应用程序的 URL,它指定了应用程序监听的端口号和路径。
    • environmentVariables:一个对象,用于定义环境变量。例如,你可以将 ASPNETCORE_ENVIRONMENT 设置为 “Development”,以指示应用程序运行在开发环境下。
  • https 配置

    • 它与 http 配置非常相似,但主要用于配置应用程序在 HTTPS 协议下的启动行为。
    • applicationUrl 字段同时包含了 HTTPS 和 HTTP 的 URL,以确保应用程序能够同时处理加密和非加密的请求。
  • IIS Express 配置

    • 它指定了使用 IIS Express 作为托管服务器时的启动配置。
    • commandName 被设置为 “IISExpress”,以区分于其他启动命令。
    • launchBrowser 和 environmentVariables 字段的含义与前面提到的配置相同。
    • IIS Express 配置文件只能在 Windows 上使用,并使用 IIS Express 来运行你的应用。
4.3.3 ASP.NET Core中的Kestrel

第3章我们讲过 WebApplication.CreateBuilder(args) 方法执行了多个关键任务,构建了一个完整的ASP.NET Core应用程序的基础设施:

  1. 初始化服务容器:它创建了一个依赖注入容器,这个容器被称为服务容器或服务提供者,它负责管理应用程序组件之间的依赖关系,确保在需要时能够提供所需的服务,如数据库连接对象、中间件和其他工具类。

  2. 配置日志系统:方法内初始化了日志框架,使得开发者能够在应用程序的各个部分轻松地记录诊断信息,包括调试消息、警告和错误,以支持故障排查和性能分析。

  3. 设置应用主机和配置:该方法还配置了应用程序的主机,这是运行Web应用的基础。它包括定义应用程序的入口点、选择HTTP服务器(如Kestrel)以及设置访问应用的URL等网络配置。

  4. 提供扩展点:WebApplicationBuilder类提供了丰富的扩展方法,允许开发者进一步定制应用程序的行为,比如注册额外的服务、配置特定的日志提供者或是调整中间件顺序等。

  5. 构建WebApplication实例:通过调用Build()方法,WebApplicationBuilder构建了一个WebApplication实例,这个实例包含了所有配置和服务,是实际运行Web应用的对象。它准备好了接收和处理HTTP请求,执行业务逻辑,并返回响应。

我们之所以重提Kestrel,是因为它在理解ASP.NET Core的工作原理中至关重要。你是否好奇,当按下“F5”键启动项目时,背后隐藏着怎样一套有序的执行流程呢?

控制台应用程序的基础

在.NET环境中,控制台应用程序是一种基于命令行界面的程序,它通常没有图形用户界面(GUI)。在ASP.NET Core中,应用程序的入口点是一个Main方法,这个方法通常位于一个名为Program.cs的文件中。另一种情况是当你使用顶级语句编写程序时,编译器会将你的代码包装在一个自动生成的 Program 类中,并创建一个入口点方法(不是 Main)。无论那种情况都使得ASP.NET Core应用程序在结构上类似于控制台应用程序。

Web服务器的托管

ASP.NET Core应用程序不依赖于IIS(Internet Information Services)或任何其他外部Web服务器来运行。相反,它们自己托管一个Web服务器,默认情况下是Kestrel。Kestrel是一个跨平台的Web服务器,提供了高性能和异步I/O操作。

Kestrel的特点

  • 跨平台:Kestrel可以在Windows、Linux和macOS上运行。
  • 高性能:经过优化以处理高并发连接和低延迟请求。
  • 轻量级:资源消耗低,适用于资源受限的环境。
  • 安全性:支持HTTPS并经过强化以抵御Web服务器漏洞。

直接处理请求

当ASP.NET Core应用程序启动时,它会配置并启动Kestrel服务器,监听来自客户端(如Web浏览器)的HTTP请求。一旦请求到达,Kestrel会将其转发给ASP.NET Core的中间件管道进行处理。中间件管道是一系列中间件组件的集合,它们按照特定的顺序处理请求,并最终生成响应。

部署选项

虽然ASP.NET Core应用程序可以自己托管Kestrel服务器,但在生产环境中,通常会将Kestrel与反向代理服务器(如IIS、Nginx或Apache)结合使用。反向代理服务器负责接收来自互联网的请求,并将其转发给Kestrel服务器。这种配置可以提供额外的安全性、负载均衡和静态文件服务等功能。

当ASP.NET Core应用程序启动时,可以将其看成一个类似俄罗斯套娃样式的层次结构,最外层是控制台应用程序,它负责启动和托管整个应用程序。控制台应用程序会启动并托管自托管的Kestrel服务器,而Kestrel服务器则负责承载ASP.NET Core的中间件管道和应用程序逻辑。

“托管自托管的Kestrel服务器”可能听起来有些矛盾,但实际上它指的是一种应用程序架构模式,特别是在控制台应用程序中运行Web服务器的情况。这里的“自托管”和“托管”分别指的是两个不同的概念:

  • 自托管(self-hosted):Kestrel服务器可以作为应用程序的一部分直接运行,不需要像传统的Web服务器那样在独立的服务器进程中运行。这意味着你可以在控制台应用、Windows服务、后台工作器等任何.NET 应用类型中直接启动Kestrel,使Web服务器成为应用程序自身的一个组成部分。

  • 托管(hosting):另一方面,“托管”在这里指的是控制台应用程序作为宿主,它负责启动、停止和管理Kestrel服务器的生命周期。控制台应用程序不仅启动Kestrel,还会处理如异常捕获、日志记录、应用配置等任务,确保Kestrel在一个适当的环境中运行。

因此,当说“控制台应用程序会启动并托管自托管的Kestrel服务器”,实际上是在描述一个控制台应用如何承载和管理一个嵌入式Web服务器(Kestrel)的生命周期,使其能够处理HTTP请求并提供Web服务。

4.3.4 如何使用 launchSettings.json

端口号是计算机上用于区分不同网络服务的数字标识,端口号的选择通常是任意的,但有一些常见的端口号被约定用于特定的服务。例如,HTTP 服务通常使用端口 80,而 HTTPS 服务通常使用端口 443。然而,在开发环境中,你可以任意选择使用不同的端口号,以避免与计算机上运行的其他服务发生冲突。

当你使用 Visual Studio 启动 ASP.NET Core 应用程序时,launchSettings.json 文件中的配置将被自动读取并应用。你可以根据需要自由地修改这些配置,以适应你的开发需求。

如果你想要更改应用程序的端口号,只需在 http 或 https 配置的 applicationUrl 字段中指定新的端口号即可。例如:我们把https 配置的 applicationUrl 字段7260改为5000

"https": {"commandName": "Project","dotnetRunMessages": true,"launchBrowser": true,"applicationUrl": "https://localhost:5000;http://localhost:5035","environmentVariables": {"ASPNETCORE_ENVIRONMENT": "Development"}
}

然后重新启动项目如图:
在这里插入图片描述

4.4 .csproj项目文件

.csproj 文件是 ASP.NET Core项目中的一个关键文件,它包含了项目的配置信息和元数据。当你双击解决方案资源管理器中的项目 BookQuerySystem时,Visual Studio 会允许你编辑该项目的 .csproj 文件。在这里插入图片描述

4.4.1 .csproj 文件基础

.csproj 文件是一个 XML 文件,它定义了项目的编译选项、依赖项、目标框架等信息。在 ASP.NET Core 项目中,这个文件尤为重要,因为它指导 MSBuild(.NET 的构建系统)如何构建和打包你的应用程序。

<Project Sdk="Microsoft.NET.Sdk.Web"><PropertyGroup><TargetFramework>net8.0</TargetFramework><Nullable>enable</Nullable><ImplicitUsings>enable</ImplicitUsings></PropertyGroup></Project>
  • <Project Sdk=“Microsoft.NET.Sdk.Web”>: 这一行指定了项目使用的 SDK 是 Microsoft.NET.Sdk.Web。这个 SDK 专门为 ASP.NET Core Web 应用程序设计,提供了构建、运行和发布 Web 应用程序所需的一切。

  • <PropertyGroup>: <PropertyGroup> 元素包含了一组键值对,这些键值对定义了项目的全局属性。

    • <TargetFramework>net8.0</TargetFramework>: 这指定了项目的目标框架是 .NET 8.0。目标框架决定了项目将使用哪个版本的 .NET 库和运行时。在BookQuerySystem中,项目被配置为使用 .NET 8.0,这意味着它将能够利用该版本提供的所有新特性和改进。

    • <Nullable>enable</Nullable>: 这启用了 C# 8.0 引入的可空引用类型特性。当设置为 enable 时,编译器会强制你明确指定引用类型的可空性。

    • <ImplicitUsings>enable</ImplicitUsings>: 在 C# 10 中引入的隐式 using 指令允许你省略一些常用的命名空间引用,如 System 和 System.Collections.Generic。当 设置为 enable 时,这些隐式 using 指令会被添加到项目的编译上下文中,从而简化代码。

4.4.2 编辑 .csproj 文件

虽然通常不需要经常编辑 .csproj 文件,但在某些情况下(如添加新的依赖项、配置特定构建选项等),你可能需要直接编辑它。以下是一些编辑 .csproj 文件的建议:

  1. 使用 Visual Studio:双击项目BookQuerySystem节点在解决方案资源管理器中打开 .csproj 文件,并进行必要的更改。Visual Studio 提供了语法高亮和智能感知,使编辑过程更加容易。

  2. 手动编辑:你也可以使用任何文本编辑器(如 Notepad++、Visual Studio Code 等)来编辑 .csproj 文件。但是,请确保你了解 XML 语法和 .csproj 文件的特定结构。

  3. 添加依赖项:如果你需要添加 NuGet 包或其他项目依赖项,可以使用 Visual Studio 的 NuGet 包管理器 GUI,也可以直接在 .csproj 文件中添加 <ItemGroup> 元素和相应的 <PackageReference>或 <ProjectReference>元素。

  4. 提交更改:如果你正在使用版本控制系统(如 Git),请确保在提交更改前仔细检查 .csproj 文件,以确保没有引入不必要的错误或不一致性。

在添加依赖项时,最好使用 Visual Studio 的 NuGet 包管理器 GUI,因为它提供了更直观的界面和错误检查功能。

通过理解 .csproj 文件的结构和内容,你可以更好地控制 ASP.NET Core 项目的构建和打包过程。

总结

  • 在本章中,我们深入探讨了ASP.NET Core图书管理系统(BookQuerySystem)的项目布局和关键文件。我们首先从Project.cs文件开始,了解了它是如何作为应用程序的入口点,并配置服务和中间件的。接着,我们详细解释了顶级语句的工作原理,以及它们如何在简化代码结构的同时保持应用程序的灵活性和可扩展性。

  • 然后,我们讨论了appsettings.json文件的重要性,它用于存储应用程序的配置设置,如日志级别和允许的主机名。我们学习了如何使用IConfiguration接口在代码中读取这些配置值,并了解了如何创建环境特定的配置文件来管理不同环境下的配置。

  • 此外,我们还介绍了launchSettings.json文件,它详细定义了应用程序在开发环境下的启动配置,包括监听的端口号、是否启用SSL加密等。我们解释了如何修改这些配置以适应开发需求,并了解了ASP.NET Core中的Kestrel服务器是如何作为自托管的Web服务器来工作的。

  • 最后,我们探讨了.csproj项目文件,它是构建和打包ASP.NET Core应用程序的关键。我们了解了.csproj文件的结构和内容,包括目标框架、可空引用类型和隐式using指令等配置选项。我们还提供了编辑.csproj文件的建议,以便在需要时添加新的依赖项或配置特定的构建选项。


  1. .NET 6.0 MVC图书查询系统的教程链接:https://blog.csdn.net/baidu_38495508/article/details/121731637 ↩︎

  2. 运行时是指程序执行时依赖的环境,它提供内存管理、垃圾回收等核心服务。在C#中,这涉及到.NET运行时(也称为CLR),它是.NET Framework和.NET的一部分。C#代码通过编译器(如csc.exe)被编译成中间语言(IL)代码,并打包进程序集(.exe或.dll文件)。在程序执行时,.NET运行时加载这些程序集,并使用即时编译器(JIT)将IL编译为针对当前运行平台的机器码,然后执行这些机器码。 ↩︎

  3. 这里的编译器指的是C#编译器,也称为csc.exe,它是Microsoft.NET SDK的一部分,负责将C#源代码编译成IL(中间语言)代码,然后再由.NET运行时(runtime)处理。在C# 9及更高版本中,如果使用了顶级语句,编译器会在编译过程中自动创建一个包含顶级语句的类(通常是Program类)以及一个内部的静态方法作为入口点,这个方法不是显式在源代码中定义的Main方法,而是由编译器生成的一个内部名称的方法。这个过程简化了源代码的结构,让开发者可以更加专注于编写业务逻辑,而不必关心程序的入口点。 ↩︎

  4. URL(Uniform Resource Locator)和路由(Routing)在Web开发中是相关的概念,但不完全相同。
    URL是统一资源定位符,它是互联网上资源的唯一地址,包括协议(如http或https),服务器地址,以及用于定位特定资源的路径。例如:
    https://www.example.com/path/to/page
    URL用于在Web浏览器中输入,以便访问特定的网络资源。
    路由,特别是在ASP.NET Core这样的Web框架中,是服务器内部的一种机制,用于将HTTP请求映射到对应的处理程序,如控制器方法或API端点。路由定义了URL模式,并决定哪些URL请求应该由哪个处理程序来处理。在ASP.NET Core中,你可以使用MapGet, MapPost等方法来定义路由规则。
    所以,虽然URL和路由紧密相关,但它们是不同的概念。URL是用户在浏览器中看到的地址,而路由是服务器内部用于解析和处理URL的逻辑。 ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/875308.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

lua 游戏架构 之 游戏 AI (五)ai_autofight_find_way

这段Lua脚本定义了一个名为 ai_autofight_find_way 的类&#xff0c;继承自 ai_base 类。 lua 游戏架构 之 游戏 AI &#xff08;一&#xff09;ai_base-CSDN博客文章浏览阅读238次。定义了一套接口和属性&#xff0c;可以基于这个基础类派生出具有特定行为的AI组件。例如&…

【Python】成功解决conda创建虚拟环境时出现的CondaHTTPError: HTTP 000 CONNECTION FAILED错误

【Python】成功解决conda创建虚拟环境时出现的CondaHTTPError: HTTP 000 CONNECTION FAILED错误 &#x1f308; 欢迎莅临我的个人主页&#x1f448;这里是我深耕Python编程、机器学习和自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;并乐于分享知识与经验的小天地&a…

20240724----idea的Java环境卸载与安装

1.删除旧有的jdk https://blog.csdn.net/weixin_42168713/article/details/112162099 &#xff08;补充&#xff1a;我把用户变量和java有关的都删了&#xff09; 2.下载新的jdk百度网盘链接 链接&#xff1a;https://pan.baidu.com/s/1gkuLoxBuRAtIB1IzUTmfyQ 提取码&#xf…

Docker 部署常用中间件(redis,rabbitMQ,mysql8,es,kibana,nginx等)亲测成功~~~

Docker 部署常用中间件 在日常开发中必要的环境&#xff0c;大多数都是单点后续持续更新集群模式~~~ docker 安装reids docker pull redis:7.2.5 编辑redis.conf # 绑定地址&#xff0c;默认只允许本机访问 # bind 192.168.1.100 10.0.0.1 # bind 127.0.0.1 ::1 bind 0.0…

Vue中el的两种写法

大家好我是前端寄术区博主PleaSure乐事。今天了解到了Vue当中有关el的两种写法&#xff0c;记录下来与大家分享&#xff0c;希望对大家有所帮助。 方法一 解释 第一种方法我们直接用new创建并初始化一个新的 Vue 实例&#xff0c;并定义了 Vue 实例的数据对象&#xff0c;在给…

mac大文件清理软件哪个好 mac大文件怎么清理 苹果电脑清理软件推荐免费

mac采用固态硬盘技术&#xff0c;数据存储和系统响应速度优势明显&#xff0c;但是mac的内存弊端同样体现在其固态硬盘的技术&#xff0c;导致用户无法通过机械硬盘进行扩充内存。而我们日常使用电脑会产生大量系统垃圾、用户缓存等文件&#xff0c;平时下载的电影和大型游戏安…

前端:Vue学习 - 购物车项目

前端&#xff1a;Vue学习 - 购物车项目 1. json-server&#xff0c;生成后端接口2. 购物车项目 - 实现效果3. 参考代码 - Vuex 1. json-server&#xff0c;生成后端接口 全局安装json-server&#xff0c;json-server官网为&#xff1a;json-server npm install json-server -…

增材制造与智能制造关系

在撰写的增材制造技术与装备书籍中有着明确的描述&#xff0c;增材制造是智能制造的典型范例&#xff0c;是智能制造“类”的实例化过程。这种借助于计算机编程面向对象思想的解释可以更全面的理解增材制造和智能制造的关系。增材制造实例具备了智能制造类的属性&#xff0c;智…

钉钉 ai卡片 stream模式联调

sdk连接 新建卡片模板下载node.js sdkconfig.json 配置应用信息 启动项目npm i npm run build npm run start连接成功 获取卡片回调 注册卡片回调事件调用https://api.dingtalk.com/v1.0/card/instances 创建卡片实例&#xff0c;返回实例Id //参数结构 {"cardTempla…

Redis 7.x 系列【30】集群管理命令

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Redis 版本 7.2.5 源码地址&#xff1a;https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 概述2. 集群信息2.1 CLUSTER INFO 3. 节点管理3.1 CLUSTER MYID3.2 CLUSTER NODES3…

LC617-合并二叉树

文章目录 1 题目描述2 思路优化代码完整输入输出 参考 1 题目描述 https://leetcode.cn/problems/merge-two-binary-trees/description/ 给你两棵二叉树&#xff1a; root1 和 root2 。 将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另…

数据结构排序合集(笔记)

目录 一.插入排序与希尔排序 二.选择排序与堆排序 三.冒泡排序和快速排序 四.归并排序 五.计数排序 一.插入排序与希尔排序 时间复杂度空间复杂度稳定性插入排序O&#xff08;N^2&#xff09;O(1)稳定希尔排序O(N^1.3)O(1)不稳定 插入排序&#xff1a; 希尔排序&#xff…

报红:找不到名称ref ts(2304)、‘ref‘ is not defined. eslint(no-undef)

接上篇 在上篇介绍了使用 unplugin-auto-import 和 unplugin-vue-components 配置完成后&#xff0c;项目可以正常运行&#xff0c;并且页面也正常显示&#xff0c;但vscode里就是报红 这个报红可能是由于 ts 发出的&#xff0c;也可能是由于 eslint 发出的 具体可以用鼠标…

打卡第22天------回溯算法

开始学习了,希望我可以尽快成功上岸! 一、回溯理论基础 什么是回溯法?回溯法也可以叫做回溯搜索法,它是一种搜索的方式。 回溯是递归的副产品,只要有递归就会有回溯。 回溯法的效率回溯法的本质是穷举,穷举所有可能,然后找出我们想要的答案。如果想让回溯法高效一些,可…

Docker-Compose实现MySQL之主从复制

1. 主服务器(IP:192.168.186.77) 1.1 docker-compose.yml services:mysql-master:image: mysql:latest # 使用最新版本的 MySQL 镜像container_name: mysql-master # 容器的名称environment:MYSQL_ROOT_PASSWORD: 123456 # MySQL root 用户的密码MYSQL_DATABASE: masterd…

我用Tauri开发的待办效率工具开源了!

开源仓库地址 gitee Git仓库地址:https://gitee.com/zhanhongzhu/zhanhongzhu.git 应用地址 windows应用地址下载 https://kestrel-task.cn 具体内容 也可以看&#x1f389;使用Taurivitekoa2mysql开发了一款待办效率应用 这篇文章。 &#x1f4bb;技术栈 Tauri: Tauri…

传统自然语言处理(NLP)与大规模语言模型(LLM)详解

自然语言处理&#xff08;NLP&#xff09;和大规模语言模型&#xff08;LLM&#xff09;是理解和生成人类语言的两种主要方法。本文将介绍传统NLP和LLM的介绍、运行步骤以及它们之间的比较&#xff0c;帮助新手了解这两个领域的基础知识。 传统自然语言处理&#xff08;NLP&…

Redis分布式系统中的主从复制

本篇文章主要对Redis的主从复制进行讲解。主要分析复制的原理&#xff0c;包括:建立复制、全量复制、部分复制、全量复制、心跳检测等。希望本篇文章会对你有所帮助。 文章目录 一、主从复制简介 二、配置主从复制模式 断开主从复制 安全性 只读 传输延迟 三、拓扑结构 四、主…

如何利用VPN和NAT技术实现高效安全的网络连接

文章目录 **什么是VPN&#xff1f;****专用地址的使用****VPN的工作原理****远程接入VPN****VPN的应用实例****什么是NAT&#xff1f;****NAT的工作原理****NAPT&#xff08;网络地址与端口号转换&#xff09;****NAT的优势和局限****NAT的应用实例****VPN和NAT的结合****常见问…

C++ | Leetcode C++题解之第279题完全平方数

题目&#xff1a; 题解&#xff1a; class Solution { public:// 判断是否为完全平方数bool isPerfectSquare(int x) {int y sqrt(x);return y * y x;}// 判断是否能表示为 4^k*(8m7)bool checkAnswer4(int x) {while (x % 4 0) {x / 4;}return x % 8 7;}int numSquares(i…