当前位置: 首页 > news >正文

ABP VNext + .NET Minimal API:极简微服务快速开发

ABP VNext + .NET Minimal API:极简微服务快速开发 💨


📚 目录

  • ABP VNext + .NET Minimal API:极简微服务快速开发 💨
    • 1. 引言 🚀
      • TL;DR ✨
    • 2. 环境与依赖 🛠️
    • 3. 项目结构与入口 📂
    • 4. `Program.cs` 📝
      • 中间件管道(推荐顺序)⏱️
    • 5. 定义 ABP 模块 🏗️
    • 6. 实体、DTO 与 DbContext 📦
      • 实体:`Domain/Entities/User.cs`
      • DTO:`Application/Dtos/UserDto.cs`
      • DTO:`Application/Dtos/CreateUserDto.cs`
      • DbContext:`Domain/MyDbContext.cs`
    • 7. 应用服务接口与实现 🛠️
      • 接口:`Application/IUserAppService.cs`
      • 实现:`Application/UserAppService.cs`
    • 8. AOP 拦截器与调用流程 🔄
    • 9. 配置与环境管理 🌍
    • 10. 安全与鉴权 🛡️
    • 11. 中间件与辅助功能 🔧
    • 13. 最佳实践建议 📈


1. 引言 🚀

TL;DR ✨

  • 🔥 极简上手:用 .NET Minimal API + ABP VNext,仅需一个 Program.cs 即可启动轻量级微服务
  • 🛡️ 保留核心能力:依然拥有 ABP 的依赖注入(DI)、AOP 拦截器、配置管理、审计日志等特性
  • 🎉 即开即用:ProblemDetails 异常格式、Swagger/OpenAPI、多版本 API 文档、API 版本管理、健康检查、CORS、多语言本地化一键配置
  • 高性能、高可用:Serilog 日志 + Kestrel 原生优化 + Docker Compose,启动秒级响应

2. 环境与依赖 🛠️

  • .NET SDK:6 +

  • ABP VNext:6.x +

  • 数据库:PostgreSQL(生产)、In-Memory(测试)

  • 关键 NuGet 包

    dotnet add package Volo.Abp.AspNetCore.Builder  
    dotnet add package Volo.Abp.Modularity  
    dotnet add package Volo.Abp.EntityFrameworkCore.PostgreSql  
    dotnet add package Volo.Abp.AutoMapper  
    dotnet add package Volo.Abp.AspNetCore.Serilog        # Serilog 丰富器  
    dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer  
    dotnet add package Swashbuckle.AspNetCore  
    dotnet add package Asp.Versioning.Http  
    dotnet add package Asp.Versioning.Mvc.ApiExplorer      # 版本化 ApiExplorer  
    dotnet add package Hellang.Middleware.ProblemDetails    # ProblemDetails 中间件  
    dotnet add package Serilog  
    dotnet add package Serilog.Sinks.Console               # Serilog 控制台 Sink  
    dotnet add package StackExchange.Redis  
    

3. 项目结构与入口 📂

MyMinimalService/
├─ Program.cs
├─ Modules/
│    └─ MyServiceModule.cs
├─ Application/
│    ├─ Dtos/
│    │    ├─ UserDto.cs
│    │    └─ CreateUserDto.cs
│    └─ IUserAppService.cs
├─ Domain/
│    ├─ Entities/
│    │    └─ User.cs
│    └─ MyDbContext.cs
└─ appsettings.json

4. Program.cs 📝

using System.Text.Json;
using System.Text.Json.Serialization;
using Hellang.Middleware.ProblemDetails;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http.Json;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.Versioning;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using Serilog;
using Volo.Abp;
using Volo.Abp.Autofac;
using Volo.Abp.AspNetCore.Builder;     // 确保 AddApplication 扩展可用
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.EventBus;                // 确保 AddAbpEventBus 扩展可用
using Volo.Abp.EntityFrameworkCore;var builder = WebApplication.CreateBuilder(args);// 1. Serilog 全局配置 🔥
builder.Host.UseSerilog((ctx, lc) =>
{lc.ReadFrom.Configuration(ctx.Configuration).Enrich.FromLogContext().Enrich.WithProperty("Application", ctx.HostingEnvironment.ApplicationName).WriteTo.Console();
});// 2. 使用 Autofac 容器,确保 ABP AOP 拦截器生效 🛡️
builder.Host.UseAutofac();// 3. 注册 ABP 模块化支持(包含 ASP.NET Core 特性)📦
builder.Services.AddApplication<MyServiceModule>();// 4. 本地化:资源文件路径 🌐
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");// 5. ProblemDetails 异常格式化 ⚠️
builder.Services.AddProblemDetails(opts =>
{opts.MapToStatusCode<Exception>(StatusCodes.Status500InternalServerError);
});// 6. 身份验证与授权 🔒
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => {options.Authority = builder.Configuration["Auth:Issuer"];options.Audience  = builder.Configuration["Auth:Audience"];});
builder.Services.AddAuthorization();// 7. 启用 ABP 事件总线(自动注册 AOP 拦截器)🔄
builder.Services.AddAbpEventBus();// 8. JSON 序列化优化 📲
builder.Services.Configure<JsonOptions>(opts =>
{opts.SerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;opts.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
});// 9. API 版本化 📑
builder.Services.AddApiVersioning(opts =>
{opts.AssumeDefaultVersionWhenUnspecified = true;opts.DefaultApiVersion = new ApiVersion(1, 0);opts.ReportApiVersions = true;opts.ApiVersionReader = new UrlSegmentApiVersionReader();
});
builder.Services.AddVersionedApiExplorer(opts =>
{opts.GroupNameFormat = "'v'VVV";opts.SubstituteApiVersionInUrl = true;
});// 10. Swagger/OpenAPI 🛠️
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(opts =>
{// 在此阶段 BuildServiceProvider 有轻微容器重复,但示例中可用var provider = builder.Services.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();foreach (var desc in provider.ApiVersionDescriptions){opts.SwaggerDoc(desc.GroupName, new OpenApiInfo {Title   = "MyMinimalService",Version = desc.ApiVersion.ToString()});}
});// 11. 健康检查 + Redis 缓存 ❤️
builder.Services.AddHealthChecks().AddDbContextCheck<MyDbContext>("db").AddRedis(builder.Configuration["Redis:ConnectionString"], name: "redis");
builder.Services.AddStackExchangeRedisCache(opts =>
{opts.Configuration = builder.Configuration["Redis:ConnectionString"];
});// 12. CORS 🌐
builder.Services.AddCors(opts =>
{opts.AddDefaultPolicy(p =>p.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
});var app = builder.Build();// 13. 初始化 ABP 应用 🔧
app.InitializeApplication();

中间件管道(推荐顺序)⏱️

ProblemDetails ⚠️
AbpExceptionHandling 🛠️
本地化 🌐
CORS 🌐
Serilog 请求日志 📋
Authentication 🔒
Authorization 🛡️
AbpSerilogEnrichers 📝
Swagger 🛠️
HealthCheck ❤️
app.UseProblemDetails();                     // RFC7807 异常格式
app.UseAbpExceptionHandling();               // ABP 全局异常处理
app.UseAbpRequestLocalization();             // 本地化
app.UseCors();                               // 跨域
app.UseSerilogRequestLogging();              // Serilog 请求日志
app.UseAuthentication();                     // 验证
app.UseAuthorization();                      // 授权
app.UseAbpSerilogEnrichers();                // ABP Serilog 丰富器
app.UseSwagger();
app.UseSwaggerUI(c =>
{var provider = app.Services.GetRequiredService<IApiVersionDescriptionProvider>();foreach (var desc in provider.ApiVersionDescriptions){c.SwaggerEndpoint($"/swagger/{desc.GroupName}/swagger.json", desc.GroupName);}
});
app.UseHealthChecks("/health");// 极简路由定义 📍
app.MapGroup("/api/v{version:apiVersion}/users").MapGet("/{id}", (Guid id, IUserAppService svc) => svc.GetAsync(id)).MapGet("/",        (IUserAppService svc) => svc.GetListAsync()).MapPost("/",       (CreateUserDto dto, IUserAppService svc) => svc.CreateAsync(dto)).RequireAuthorization();app.Run();

5. 定义 ABP 模块 🏗️

using Volo.Abp;
using Volo.Abp.Autofac;
using Volo.Abp.AspNetCore.Builder;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;namespace MyMinimalService.Modules
{[DependsOn(typeof(AbpAspNetCoreModule),       // ASP.NET Core 特性支持typeof(AbpAutofacModule),typeof(AbpEntityFrameworkCoreModule),typeof(AbpAspNetCoreSerilogModule)  // Serilog 丰富器模块)]public class MyServiceModule : AbpModule{public override void ConfigureServices(ServiceConfigurationContext context){Configure<AbpDbContextOptions>(opts => opts.UseNpgsql());context.Services.AddAbpDbContext<MyDbContext>(opts =>{opts.AddDefaultRepositories(true);});context.Services.AddAutoMapperObjectMapper<MyServiceModule>();Configure<AbpAutoMapperOptions>(opt => opt.AddMaps<MyServiceModule>());}}
}

6. 实体、DTO 与 DbContext 📦

实体:Domain/Entities/User.cs

using System;
using Volo.Abp.Domain.Entities.Auditing;namespace MyMinimalService.Domain.Entities
{/// <summary>/// 用户实体,继承了审计字段(CreationTime、CreatorId、LastModificationTime 等)/// </summary>public class User : AuditedAggregateRoot<Guid>{/// <summary>/// 用户名/// </summary>public string Name { get; set; }protected User() { }public User(Guid id, string name): base(id){Name = name;}}
}

DTO:Application/Dtos/UserDto.cs

using System;namespace MyMinimalService.Application.Dtos
{/// <summary>/// 用户数据传输对象/// </summary>public class UserDto{public Guid Id { get; set; }public string Name { get; set; }}
}

DTO:Application/Dtos/CreateUserDto.cs

using System.ComponentModel.DataAnnotations;namespace MyMinimalService.Application.Dtos
{/// <summary>/// 创建用户时的输入 DTO/// </summary>public class CreateUserDto{[Required][StringLength(128, MinimumLength = 1)]public string Name { get; set; }}
}

DbContext:Domain/MyDbContext.cs

using Microsoft.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using MyMinimalService.Domain.Entities;namespace MyMinimalService.Domain
{/// <summary>/// 应用的 EF Core 上下文,配置了 User 实体和默认仓储/// </summary>public class MyDbContext : AbpDbContext<MyDbContext>{public DbSet<User> Users { get; set; }public MyDbContext(DbContextOptions<MyDbContext> options): base(options){}protected override void OnModelCreating(ModelBuilder builder){base.OnModelCreating(builder);builder.Entity<User>(b =>{b.ToTable("AppUsers");                        // 自定义表名b.HasKey(x => x.Id);b.Property(x => x.Name).IsRequired().HasMaxLength(128);});}}
}

7. 应用服务接口与实现 🛠️

接口:Application/IUserAppService.cs

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using MyMinimalService.Application.Dtos;namespace MyMinimalService.Application
{/// <summary>/// 定义用户相关的应用服务接口/// </summary>public interface IUserAppService : IApplicationService{/// <summary>/// 获取指定 Id 的用户/// </summary>Task<UserDto> GetAsync(Guid id);/// <summary>/// 获取所有用户列表/// </summary>Task<List<UserDto>> GetListAsync();/// <summary>/// 创建一个新用户/// </summary>Task<UserDto> CreateAsync(CreateUserDto input);}
}

实现:Application/UserAppService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using MyMinimalService.Application.Dtos;
using MyMinimalService.Domain.Entities;namespace MyMinimalService.Application
{/// <summary>/// 用户应用服务实现,包含基本的增删改查/// </summary>public class UserAppService : ApplicationService, IUserAppService{private readonly IRepository<User, Guid> _repository;public UserAppService(IRepository<User, Guid> repository){_repository = repository;}/// <summary>/// 根据 Id 获取一个用户,需认证/// </summary>[Authorize]public async Task<UserDto> GetAsync(Guid id){var entity = await _repository.GetAsync(id);return ObjectMapper.Map<User, UserDto>(entity);}/// <summary>/// 获取所有用户列表/// </summary>public async Task<List<UserDto>> GetListAsync(){var entities = await _repository.GetListAsync();return entities.Select(u => ObjectMapper.Map<User, UserDto>(u)).ToList();}/// <summary>/// 创建新用户/// </summary>public async Task<UserDto> CreateAsync(CreateUserDto input){var user = new User(GuidGenerator.Create(), input.Name);var created = await _repository.InsertAsync(user);return ObjectMapper.Map<User, UserDto>(created);}}
}

8. AOP 拦截器与调用流程 🔄

客户端请求
ABP 拦截管道
验证拦截器
日志拦截器
业务方法
审计拦截器
返回结果

9. 配置与环境管理 🌍

  • 加载顺序appsettings.jsonappsettings.{环境}.json → 环境变量

  • 示例 appsettings.json

    {"ConnectionStrings": {"Default": "Host=localhost;Database=mydb;Username=user;Password=pass"},"Redis": {"ConnectionString": "localhost:6379"},"Auth": {"Issuer": "https://auth.example.com","Audience": "MyMinimalService"}
    }
    
  • 支持 Kubernetes Secret、Vault 等插件扩展


10. 安全与鉴权 🛡️

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>{options.Authority = cfg["Auth:Issuer"];options.Audience  = cfg["Auth:Audience"];});
app.UseAuthentication();
app.UseAuthorization();
  • .RequireAuthorization()[Authorize] 保护端点
  • 支持 ABP 的 Policy 与 PermissionChecker

11. 中间件与辅助功能 🔧

  • ProblemDetails:统一异常格式
  • AbpExceptionHandling:ABP 全局异常处理
  • Localization:多语言支持
  • Serilog:日志丰富器 + 请求日志
  • Swagger/OpenAPI:多版本文档
  • HealthChecks:健康探针
  • CORS:跨域配置

13. 最佳实践建议 📈

  • DI 生命周期DbContext 保持默认 Scoped

  • Kestrel 调优

    "Kestrel": {"Limits": { "MaxConcurrentConnections": 1000 }
    }
    
  • 分布式缓存:Redis (AddStackExchangeRedisCache) 实现高可用


http://www.dtcms.com/a/270403.html

相关文章:

  • B. Shrinking Array/缩小数组
  • Web后端实战:(部门管理)
  • 数据结构*搜索树
  • 二极管常见种类及基本原理
  • 【牛客刷题】小红的red字符串
  • MyBatis-Plus:提升数据库操作效率的利器
  • AB实验的长期影响
  • 【数据结构】复杂度分析
  • SpringBoot框架完整学习指南
  • [创业之路-489]:企业经营层 - 营销 - 如何将缺点转化为特点、再将特点转化为卖点
  • 钉钉企业应用开发技巧:在单聊会话中实现互动卡片功能
  • 学习日记-spring-day43-7.8
  • 基于物联网架构的温室环境温湿度传感器节点设计
  • 扣子Coze纯前端部署多Agents
  • WouoUI-Page移植
  • Java-Collections、Map
  • H3初识——入门介绍之常用中间件
  • 11款常用C++在线编译与运行平台推荐与对比
  • ffmpeg 中config 文件一些理解
  • Flutter基础(前端教程②-卡片列表)
  • study_WebView介绍
  • MYSQL进阶知识
  • 在keil中使用stlink下载程序报错Invalid ROM Table
  • Day07_C语言IO进程线程(重难点)
  • TensorFlow 和PyTorch的全方位对比和选择建议
  • Latex几种常用的花体
  • [2-02-02].第04节:环境搭建 - Linux搭建ES集群环境
  • [RPA] 影刀RPA基本知识
  • Kafka多组消费:同一Topic,不同Group ID
  • NV298NV312美光固态闪存NW639NW640