网关和服务发现

构建和设计 API 网关 API 网关是一个服务器,它是客户端和后端服务之间的中介。它接收来自客户端的请求,然后将这些请求转发到后端服务。API 网关还可以执行其他任务,例如身份验证、监视、负载平衡、缓存、请求分析和日志记录。 BFF 模式聚合多个服务 API 网关可以聚合多个服务,基于 BFF(后端用于前端)模式,当客户端请求数据时,API 网关可以调用多个服务来获取数据,然后将数据聚合到一个响应中返回给客户端,以减少客户端与后端服务之间的通信次数,从而提高性能。 常见的 API 网关 Nginx、Envoy、Ocelot、Yarp、Zuul、Kong、Traefik、Tyk、Ambassador、Gloo、AWS API Gateway、Azure API Management、Google Cloud Endpoints、Apigee、MuleSoft Anypoint API Gateway、WSO2 API Manager、TIBCO Mashery、3scale API Management、Akana、CA API Gateway、Dell Boomi、DreamFactory、IBM API Connect、Mashape、Mashery、MuleSoft Anypoint Platform、OpenLegacy、Oracle API Platform Cloud Service、Repre。 基于.NET 的开源 API 网关 Ocelot 和 Yarp 是一个基于.NET 的开源 API 网关,它可以用于构建和设计微服务架构中的 API 网关。Yarp 提供了很多功能,例如路由、负载平衡、认证、授权、限流、熔断、重试、缓存、请求转发、请求重写、请求日志、响应缓存、响应压缩、响应缓存、响应重写、响应日志、监视、跟踪、跨域、安全、性能、可扩展性、可配置性、可管理性、可监视性、可测试性、可部署性、可维护性、可扩展性、可升级。 Github 开源仓库 官方参考文档 使用 Yarp 构建和设计 API 网关 dotnet add package Yarp.ReverseProxy 使用配置文件配置 Yarp { "ReverseProxy": { "Routes": { "testserviceRoute": { "ClusterId": "testServiceCluster", "Match": { "Path": "testservice/{**remainder}" }, "Transforms": [ { "PathPattern": "{**remainder}" } ] } }, "Clusters": { "testServiceCluster": { "Destinations": { "testServiceCluster/destination1": { "Address": "http://identityservice" } } } } } } .NET 中的服务发现 服务发现是一种用于发现和定位服务的机制,它可以帮助客户端找到服务的位置和地址。服务发现可以用于构建和设计微服务架构中的 API 网关,以便客户端可以通过 API 网关访问后端服务。 ...

2026年3月10日

用户界面和设计语言

用户体验 用户体验(User Experience,简称 UX)是用户在使用产品时的感受,是一个综合性的概念,包括用户对产品的感知、情感、态度、情绪等。用户体验设计(User Experience Design,简称 UXD)是一种以用户为中心的设计方法,目的是提高用户满意度,提高用户对产品的认知和使用。 颜色、字体、布局、交互等因素都会影响用户体验,因此在设计用户界面时需要考虑用户体验,提供简洁、直观、易用的界面,以提高用户满意度。 扁平化和拟物化 扁平化设计(Flat Design)是一种简洁、直观的设计风格,强调简单、明了的界面设计,去除了繁琐的装饰和冗余的元素,使用户更容易理解和操作。拟物化设计(Skeuomorphism)是一种仿真真实物体的设计风格,强调真实感和细节,使用户更容易理解和操作。 搜索 Flat vs Skeuomorphism 了解更多信息。 常见的设计语言 Google Material Design、Microsoft Fluent Design System、Alibaba Ant Design … Material Design 设计语言 https://material.io/design 组件库 https://github.com/MudBlazor/MudBlazor https://github.com/MudBlazor/ Fluent Design System 设计语言 https://www.microsoft.com/design/fluent 组件库 https://github.com/microsoft/fast-blazor Ant Design 设计语言 https://ant.design 组件库 https://github.com/ant-design-blazor/ant-design-blazor 商业组件库 https://github.com/radzenhq/radzen-blazor 原型工具 MasterGo 和 Figma 是两个常用的原型工具,可以用来设计和制作用户界面原型,提供了丰富的组件库和交互效果,可以帮助设计师快速制作用户界面原型。 设计令牌 设计令牌(Design Tokens)是一种用来定义设计系统的方法,包括颜色、字体、间距、阴影等设计元素,可以帮助设计师和开发者快速创建一致的设计风格,提高设计效率。 选择组件 风格统一、易用性、可定制性、性能优化、文档完善、社区活跃、维护更新、商业授权等因素都会影响组件库的选择。 互补色 互补色是指在色彩环中相对位置相反的两种颜色,当两种互补色放在一起时,会产生强烈的对比效果,使得两种颜色更加突出。互补色的组合通常会产生视觉冲击,因此在设计中需要谨慎使用,浏览器开发者工具监测对比度,以确保用户体验。 应用案例 Aspire 的仪表盘设计是基于 Fluent Design 的,采用了扁平化设计风格,简洁、直观、易用,提高了用户体验。

2026年3月10日

用于生成初始数据的提供程序

数据播种是使用一组初始数据填充数据库的过程,通常在数据库首次创建时执行,这些数据通常是静态的,不会随时间变化,数据播种通常用于填充一些基本数据,例如用户、角色、权限、商品、分类等。 通用接口设计 public interface IDataSeedingProvider { Task SeedingAsync(IServiceProvider serviceProvider); } 实现具体接口 public class DataSeedingProvider(UserManager<User> userManager) : IDataSeedingProvider { public async Task SeedingAsync(IServiceProvider ServiceProvider) { var user = await userManager.FindByNameAsync("admin"); if (user == null) { await userManager.CreateAsync(new User { UserName = "admin", Email = "admin@test.com" }, "admin"); } } } 在容器中注册 builder.Services.AddTransient<IDataSeedingProvider, DataSeedingProvider>(); 自动执行扩展 public static class DataSeedingExtensions { public static IApplicationBuilder UseDataSeedingProviders(this IApplicationBuilder app) { using var serviceScope = app.ApplicationServices.CreateScope(); var dataSeedingProviders = serviceScope.ServiceProvider.GetServices<IDataSeedingProvider>(); foreach (IDataSeedingProvider dataSeedingProvider in dataSeedingProviders) { dataSeedingProvider.SeedingAsync(serviceScope.ServiceProvider).Wait(); } return app; } } 自动注册实现 public static class DataSeedingExtensions { public static IServiceCollection AddDataSeedingProviders(this IServiceCollection services, Assembly? assembly = null) { assembly ??= Assembly.GetCallingAssembly(); var dataSeedProviders = assembly.ExportedTypes.Where(t => t.IsAssignableTo(typeof(IDataSeedingProvider)) && t.IsClass); dataSeedProviders.ToList().ForEach(t => services.AddTransient(typeof(IDataSeedingProvider), t)); return services; } } 执行顺序问题 自动注册的提供程序的执行顺序是不确定的,如果需要确定执行顺序,可以设计 Order 属性,然后在 UseDataSeedingProviders 方法中按照 Order 属性排序执行。 在微服务中使用 builder.Services.AddDataSeedingProviders(); app.UseDataSeedingProviders();

2026年3月10日

在 Aspire 中集成 PostgreSQL 数据库

在 Host 项目中添加 PostgreSQL 数据库 dotnet add package Aspire.Hosting.PostgreSQL var builder = DistributedApplication.CreateBuilder(args); var postgres = builder.AddPostgres("postgres"); var postgresdb = postgres.AddDatabase("postgresdb"); var exampleProject = builder.AddProject<Projects.ExampleProject>().WithReference(postgresdb); 添加 PostgreSQL pgAdmin 资源 var postgres = builder.AddPostgres("postgres").WithPgAdmin(); 添加 PostgreSQL pgWeb 资源 var postgres = builder.AddPostgres("postgres").WithPgWeb(); 在最终的应用中引用 PostgreSQL 数据库 dotnet add package Aspire.Npgsql.EntityFrameworkCore.PostgreSQL builder.AddNpgsqlDbContext<IdentityServiceDbContext>(connectionName: DbConstants.ConnectionStringName, configureDbContextOptions: options => { new NpgsqlDbContextOptionsBuilder(options).MigrationsHistoryTable(DbConstants.MigrationsHistoryTableName); });

2026年3月10日

在项目中添加文件头注释

文件头注释 文件头注释是一种用于说明文件版权和许可的注释。它通常包括版权声明、许可证信息、作者信息和其他相关信息。文件头注释是一种很好的实践,可以帮助开发人员了解文件的版权和许可信息。 版权申明规范 // Copyright (c) HelloShop Corporation. All rights reserved. // See the license file in the project root for more information. namespace HelloShop.AppHost { internal class Class1 { } } 关于 EditorConfig 配置文件 为跨不同编辑器和 IDE 处理同一项目的多个开发人员保持一致的编码风格。 Visual Studio 2019 及更高版本支持 EditorConfig 文件,可以在 Visual Studio 中使用 EditorConfig 文件来定义和维护代码样式设置。 版权说明模板 file_header_template = Copyright (c) HelloShop Corporation. All rights reserved.\nSee the license file in the project root for more information. 对于文件名,可以使用 {fileName} 作为占位符。

2026年3月10日

制作动态流程图和架构图

微软 Visio 工具 Visio 是微软的画图工具,非常强大,但是收费,而且只能在 Windows 系统上使用,不支持 Mac 和 Linux 系统,虽然微软推出了 Visio Online,但是功能还是比较弱,而且收费。 开源 Drawio 工具 Drawio 是一个开源的画图工具,支持在线和桌面两种方式,支持多种格式,支持多种平台,支持多种语言,支持多种图形,支持多种导出格式,支持多种插件,支持多种集成方式,也支持在 Visual Studio Code 中使用插件的方式画图。 矢量图和位图 矢量图是由数学公式描述的图形,可以无限放大,不会失真,位图是由像素点描述的图形,放大会失真。 画图入口 Drawio 官网 在线画图 容器和容器大小缩放 设置图形 Container 属性为 true,可以将多个图形组合成一个图形,然后可以对这个图形进行缩放,设置 Collapsed 属性为 true,可以将图形折叠起来,只显示标题。设置 Resizable 属性为 false,可以禁止容器子图形缩放。 浮动链接和固定链接 浮动链接是指链接的位置随着图形的移动而移动,固定链接是指链接的位置不随着图形的移动而移动,可以添加自定义连接点。 拖动连接线文字 设置连接线文字可以拖动,可以将连接线文字拖动到连接线的任意位置,可以自定难以连接点的位置。 连接线的样式和反转 可以设置连接线的样式,可以设置连接线的反转,可以设置连接线的弯曲程度。 图形和连接线文字位置 设置文字位置,可以将文字放在图形或连接线左上角,设置文字位置为中心,可以将文字放在图形的中心。 连接线添加航点 可以在连接线上添加航点,可以在连接线上添加箭头,可以在连接线上添加标签。 任何目标可设置链接 可以设置任何对象的超级链接,可以设置连接线的超级链接,可以设置图形的超级链接。 替换图形 可以将新图形拖动到现有图形上替换图形,替换后,图形的属性和连接线都会保留。 对齐方式和分布方式 可以设置图形的对齐方式,可以设置图形的分布方式。 带着样式画图 可以带着样式画图,可以将样式应用到图形上,也可以清除默认样式。 嵌入图像和在线图像 理解几何图形,图形库图形,嵌入图像,在线图像的区别。 嵌入 SVG 图像修改样式 使用阿里图标库 iconfont 找图,可以下载 SVG 图像,然后嵌入到 Drawio 中,可以修改 SVG 图像的样式,但需要配置规则,如下代码。 ...

2026年3月10日

自动迁移和数据库初始化

生成迁移脚本 dotnet ef migrations add InitialCreate --output-dir Infrastructure/Migrations 手动将最新迁移脚本应用到数据库 dotnet ef database update 使用代码创建数据库 await dbContext.Database.EnsureCreatedAsync(); EnsureCreatedAsync 会创建数据库(如果不存在),并会创建所有表,但不会应用迁移脚本,适用于开发环境。 使用代码将最新迁移脚本应用到数据库 await dbContext.Database.MigrateAsync(); MigrateAsync 会应用迁移脚本,如果数据库不存在,会先创建数据库,适用于生产环境。 注意事项 如果先前已经使用 EnsureCreatedAsync 创建了数据库,再使用 MigrateAsync 会抛出异常,因为数据库和所有表已经存在,因为迁移中有创建表的操作脚本。 如果数据库不存在,使用 MigrateAsync 会先创建数据库,再创建迁移历史表,然后再应用迁移脚本,但这个过程中会打印一些错误警告信息,虽然可以忽略,但不够优雅。 优雅的做法 这里使用到一些 EF Core 的内部服务,注意他们在实现细节上的区别。 private static async ValueTask RunMigrationAsync(TDbContext dbContext, CancellationToken cancellationToken) { var strategy = dbContext.Database.CreateExecutionStrategy(); var dbCreator = dbContext.GetService<IRelationalDatabaseCreator>(); var historyRepository = dbContext.GetService<IHistoryRepository>(); await strategy.ExecuteAsync(async () => { if (!await dbCreator.ExistsAsync(cancellationToken)) { await dbCreator.CreateAsync(cancellationToken); } await historyRepository.CreateIfNotExistsAsync(); await dbContext.Database.MigrateAsync(cancellationToken); }); } 1、使用 dbCreator.ExistsAsync 先检查数据库是否存在,不存在则仅仅创建数据库(它不会创建表),这个时候得到一个空的数据库。 2、再使用 historyRepository.CreateIfNotExistsAsync 在空数据库中创建迁移历史表,用于保存迁移记录。 3、最后使用 dbContext.Database.MigrateAsync 应用迁移脚本,因为迁移脚本中的操作会在空数据库中执行,包括创建表等等操作。 4、迁移完成后,数据库中会有所有表和迁移历史表,迁移历史表中登记了最新的迁移记录。 5、后续再使用 dbContext.Database.MigrateAsync 会检查迁移历史表,如果有新的迁移脚本,会应用新的迁移脚本。 6、这样就实现了自动迁移和数据库初始化。 为了以上操作都在一个事务中执行,我们使用 dbContext.Database.CreateExecutionStrategy 创建一个执行策略, 在策略中执行上述操作。 数据库初始化的方式 在最新的 EF 9.0 建议使用 UseSeeding 和 UseAsyncSeeding 并利用初始数据对数据库进行种子设定,这些代码会在迁移时执行。 ...

2026年3月10日

自动映射实体和模型

使用 AutoMapper 自动映射实体和模型 AutoMapper 是一个对象映射工具,可以自动映射实体对象和模型对象,减少手动映射的工作量,提高开发效率,除此之外 Mapster 也是一个高性能的对象映射工具,支持源生成代码,性能更好。AutoMapper 比 Mapster 更加流行,更加成熟,更加稳定,更加易用,更加灵活,更加强大,更加全面,更加受欢迎。AutoMapper 是 .NET Foundation 的一部分,是一个开源项目,是一个非常优秀的对象映射工具。 安装 NuGet 包 dotnet add package AutoMapper 在依赖注入中注册 AutoMapper builder.Services.AddAutoMapper(Assembly.GetExecutingAssembly()); 创建映射配置文件 public class MappingProfile : Profile { public MappingProfile() { CreateMap<User, UserDto>(); CreateMap<UserDto, User>(); } } 使用 AutoMapper 映射实体和模型 public class UserService { private readonly IMapper _mapper; public UserService(IMapper mapper) { _mapper = mapper; } public UserDto GetUser(int id) { var user = _dbContext.Users.Find(id); return _mapper.Map<UserDto>(user); } public void UpdateUser(UserDto userDto) { var user = _mapper.Map<User>(userDto); _dbContext.Users.Update(user); _dbContext.SaveChanges(); } } 分页模式 常见的分页模式有两种,一种是基于页码和页大小的分页模式,一种是基于游标和页大小的分页模式。

2026年3月10日

Web 应用

2026年3月10日