2.1 项目结构与文件组织 2.1 项目结构与文件组织 (ASP.NET Core) 2.1.1 默认项目结构 使用 Visual Studio 或 .NET CLI 创建一个新的 ASP.NET Core Web API 或 MVC 项目时,会生成一个默认的项目结构。虽然可以根据需要修改,但理解这个默认结构是理解 ASP.NET Core 项目组织的基础。 典型的 ASP.NET Core 项目结构如下: 让我们逐一分析这些文件和文件夹: .vs/: Visual Studio 隐藏文件夹,存储 IDE 的特定设置,例如调试配置和用户首选项。 通常不需要手动修改此文件夹中的内容。 MyWebApp.csproj: 这是项目文件,使用 XML 格式定义了项目的依赖项、构建配置、目标框架等。
使用 Visual Studio 或 .NET CLI 创建一个新的 ASP.NET Core Web API 或 MVC 项目时,会生成一个默认的项目结构。虽然可以根据需要修改,但理解这个默认结构是理解 ASP.NET Core 项目组织的基础。
典型的 ASP.NET Core 项目结构如下:
MyWebApp/ ├── .vs/ (Visual Studio 隐藏文件夹,包含 IDE 相关配置) ├── MyWebApp.csproj (项目文件,包含依赖项、构建配置等) ├── Properties/ (包含启动配置,如 launchSettings.json) ├── Controllers/ (包含控制器类,处理 HTTP 请求) ├── Models/ (包含数据模型类) ├── Views/ (包含 MVC 视图文件) ├── wwwroot/ (包含静态资源文件,如 CSS、JavaScript、图像等) ├── appsettings.json (应用程序配置,如数据库连接字符串) ├── Program.cs (应用程序入口点) ├── Startup.cs (配置服务和请求处理管道)
让我们逐一分析这些文件和文件夹:
.vs/: Visual Studio 隐藏文件夹,存储 IDE 的特定设置,例如调试配置和用户首选项。 通常不需要手动修改此文件夹中的内容。
MyWebApp.csproj: 这是项目文件,使用 XML 格式定义了项目的依赖项、构建配置、目标框架等。 可以通过编辑此文件来添加或删除 NuGet 包、配置构建选项以及指定项目的目标运行时。
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <RootNamespace>MyWebApp</RootNamespace> </PropertyGroup> </Project>
Properties/: 此文件夹包含启动配置,例如 launchSettings.json。 launchSettings.json 定义了应用程序在开发环境中启动时的配置,例如应用程序 URL、环境变量和调试器设置。
{ "profiles": { "MyWebApp": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "applicationUrl": "https://localhost:7000;http://localhost:5000", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } }
Controllers/: 此文件夹包含控制器类,负责处理传入的 HTTP 请求并返回响应。控制器充当模型和视图之间的中介。在 Web API 项目中,控制器通常返回 JSON 或 XML 数据;在 MVC 项目中,控制器通常返回视图。
using Microsoft.AspNetCore.Mvc; namespace MyWebApp.Controllers { [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { [HttpGet] public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } } }
Models/: 此文件夹包含数据模型类,代表应用程序中的数据。 模型通常对应于数据库表或业务实体。
namespace MyWebApp.Models { public class Product { public int Id { get; set; } public string Name { get; set; } = string.Empty; public decimal Price { get; set; } } }
Views/: 此文件夹包含 MVC 视图文件,用于呈现用户界面。 视图通常使用 Razor 语法编写,Razor 是一种将 C# 代码嵌入到 HTML 中的模板引擎。视图负责显示数据并处理用户交互。
@model MyWebApp.Models.Product <h1>Product Details</h1> <p>ID: @Model.Id</p> <p>Name: @Model.Name</p> <p>Price: @Model.Price</p>
wwwroot/: 此文件夹包含静态资源文件,例如 CSS、JavaScript、图像和字体。 这些文件可以直接通过 Web 服务器访问。
appsettings.json: 此文件包含应用程序配置,例如数据库连接字符串、API 密钥和日志记录设置。 可以使用 IConfiguration 接口在应用程序代码中访问这些设置。
{ "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MyWebApp;Trusted_Connection=True;MultipleActiveResultSets=true" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }
Program.cs: 这是应用程序的入口点。 它包含 Main 方法,该方法负责创建 Web 主机并启动应用程序。
using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; namespace MyWebApp { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); } }
Startup.cs: 此类负责配置应用程序的服务和请求处理管道。 ConfigureServices 方法用于注册应用程序所需的服务,例如数据库上下文、身份验证和授权。 Configure 方法用于配置请求处理管道,例如添加中间件来处理静态文件、路由和身份验证。
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace MyWebApp { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { services.AddControllers(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } }
除了默认的项目结构之外,还可以采用一些常见的文件组织模式来提高代码的可维护性。
领域驱动设计 (DDD): DDD 是一种软件开发方法,它强调将软件设计与业务领域紧密结合。 在 ASP.NET Core 中,可以使用 DDD 来组织项目结构,将不同的业务领域划分为单独的模块或文件夹。
MyWebApp/ ├── Core/ ├── Infrastructure/ ├── Modules/ │ ├── Products/ │ │ ├── Controllers/ │ │ ├── Models/ │ │ ├── Services/ │ │ └── ... │ ├── Customers/ │ │ ├── Controllers/ │ │ ├── Models/ │ │ ├── Services/ │ │ └── ... │ └── ... ├── ...
分层架构: 分层架构是一种将应用程序划分为多个逻辑层的模式,每个层负责不同的职责。 常见的层包括表示层(UI)、业务逻辑层和数据访问层。
MyWebApp/ ├── Presentation/ (Controllers, Views) ├── Application/ (Services, Business Logic) ├── Domain/ (Entities, Interfaces) ├── Infrastructure/ (Data Access, External Services) ├── ...
特性驱动组织: 根据应用程序的特性来组织文件,例如安全性、日志记录、缓存等。
MyWebApp/ ├── Security/ │ ├── Authentication/ │ ├── Authorization/ │ └── ... ├── Logging/ ├── Caching/ ├── ...
为了更好地理解 Startup.cs 文件和请求处理管道,让我们创建一个自定义中间件来记录每个请求的执行时间。
创建一个名为 RequestTimingMiddleware.cs 的新文件:
using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using System.Diagnostics; using System.Threading.Tasks; namespace MyWebApp.Middleware { public class RequestTimingMiddleware { private readonly RequestDelegate _next; private readonly ILogger<RequestTimingMiddleware> _logger; public RequestTimingMiddleware(RequestDelegate next, ILogger<RequestTimingMiddleware> logger) { _next = next; _logger = logger; } public async Task InvokeAsync(HttpContext context) { var stopwatch = Stopwatch.StartNew(); try { await _next(context); } finally { stopwatch.Stop(); _logger.LogInformation( "Request {Path} took {ElapsedMilliseconds} ms", context.Request.Path, stopwatch.ElapsedMilliseconds); } } } }
创建一个扩展方法,以便更轻松地将中间件添加到请求管道中:
using Microsoft.AspNetCore.Builder; namespace MyWebApp.Middleware { public static class RequestTimingMiddlewareExtensions { public static IApplicationBuilder UseRequestTiming(this IApplicationBuilder builder) { return builder.UseMiddleware<RequestTimingMiddleware>(); } } }
在 Startup.cs 文件的 Configure 方法中注册中间件:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); // 添加自定义中间件 app.UseRequestTiming(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
现在,每次应用程序处理请求时,都会记录请求的路径和执行时间。
我们可以使用 Mermaid 图表来可视化项目结构。
这个图表清晰地展示了项目的主要组成部分及其关系。
ASP.NET Core 项目结构和文件组织对于构建可维护和可扩展的应用程序至关重要。 理解默认的项目结构,并根据项目需求选择合适的文件组织模式,可以显著提高开发效率和代码质量。 通过创建自定义中间件,可以更好地理解请求处理管道,并根据需要定制应用程序的行为。 记住,良好的项目结构是一个持续改进的过程,应该根据项目的增长和变化进行调整。