NexusContract.Hosting
1.0.0-preview.19
dotnet add package NexusContract.Hosting --version 1.0.0-preview.19
NuGet\Install-Package NexusContract.Hosting -Version 1.0.0-preview.19
<PackageReference Include="NexusContract.Hosting" Version="1.0.0-preview.19" />
<PackageVersion Include="NexusContract.Hosting" Version="1.0.0-preview.19" />
<PackageReference Include="NexusContract.Hosting" />
paket add NexusContract.Hosting --version 1.0.0-preview.19
#r "nuget: NexusContract.Hosting, 1.0.0-preview.19"
#:package NexusContract.Hosting@1.0.0-preview.19
#addin nuget:?package=NexusContract.Hosting&version=1.0.0-preview.19&prerelease
#tool nuget:?package=NexusContract.Hosting&version=1.0.0-preview.19&prerelease
NexusContract.Hosting
ASP.NET Core 集成层 | 零代码端点镜像生成 | 基于元数据的自动化
概述
NexusContract.Hosting 是 NexusContract 的 ASP.NET Core 集成层,提供基于元数据的契约端点自动生成能力。它消除了重复的端点映射代码,支持在启动时自动将所有契约生成为可调用的 HTTP 端点,实现真正的零代码端点生成。
核心特性
| 功能 | 描述 |
|---|---|
| 自动端点镜像 | 从元数据注册表自动生成端点,无需手动映射 |
| 零反射热路径 | 启动期编译优化,运行时零反射开销 |
| AES256 加密 | 硬件加速的敏感数据保护(支持 Redis L2 缓存) |
| 启动验证 | 完整的契约健康检查和诊断报告 |
| 路由一致性 | 与 OpenAPI/Swagger 路由完全对齐 |
快速开始
安装
dotnet add package NexusContract.Hosting
基本使用
1. 在 Program.cs 中注册服务
using NexusContract.Hosting.Configuration;
using NexusContract.Abstractions.Security;
var builder = WebApplicationBuilder.CreateBuilder(args);
// 注册 NexusContract 服务
builder.Services.AddNexusContracts(options =>
{
// 扫描包含契约的程序集
options.ScanAssemblies(typeof(TradeCreateRequest).Assembly);
// 配置选项
options.Warmup = true; // 启用预热(生产推荐)
options.ThrowOnError = true; // 错误时抛异常
options.ExitOnError = false; // 错误时退出(可选)
options.GenerateJsonReport = true; // 生成诊断报告
options.AppId = "alipay-gateway"; // 应用 ID
options.Environment = "Production"; // 环境标识
});
// 注册安全提供程序(用于敏感数据加密)
var masterKeyBase64 = Environment.GetEnvironmentVariable("NEXUS_MASTER_KEY")
?? throw new InvalidOperationException("NEXUS_MASTER_KEY environment variable not set");
builder.Services.AddSingleton<ISecretProtector>(
new AesSecurityProvider(masterKeyBase64));
var app = builder.Build();
// 映射契约端点
app.MapNexusEndpoints("/api");
app.Run();
2. 准备契约文件
// Demo.Alipay.Contract/Transactions/TradeCreateRequest.cs
using NexusContract.Abstractions.Attributes;
using NexusContract.Abstractions.Contracts;
[ApiOperation("alipay.trade.create", HttpVerb.POST)]
public class TradeCreateRequest : IApiRequest<TradeCreateResponse>
{
public string OutTradeNo { get; set; }
public decimal TotalAmount { get; set; }
public string Subject { get; set; }
public async Task<TradeCreateResponse> ExecuteAsync(
IApiExecutor executor,
string profileId,
CancellationToken cancellationToken = default)
{
return await executor.ExecuteAsync<TradeCreateResponse>(
this, profileId, cancellationToken);
}
}
3. 验证端点
启动应用后,查看控制台输出:
========================================
NexusContract 服务注册
========================================
📦 发现 20 个契约类型 (来自 1 个程序集)
✅ 契约健康检查通过:20/20 个契约已验证
========================================
[Mirror] 开始注册 20 个端点 (baseRoute: /api)
[Mirror] ✅ /api/alipay/{profileId}/trade/create
[Mirror] ✅ /api/alipay/{profileId}/trade/query
[Mirror] ✅ /api/alipay/{profileId}/trade/refund
...
[Mirror] 端点注册完成
发送请求验证:
curl -X POST http://localhost:5000/api/alipay/default/trade/create \
-H "Content-Type: application/json" \
-d '{
"outTradeNo": "2025011801",
"totalAmount": 99.99,
"subject": "Test Order"
}'
核心模块
1. 配置管理(Configuration)
NexusContractServiceExtensions
负责在启动时注册和验证所有契约。
关键职责:
- 扫描指定程序集中的契约类型
- 执行健康检查和元数据验证
- 预热投影器/水化器
- 生成诊断报告(JSON 格式)
配置选项:
public class NexusContractOptions
{
// 预热(启用则在启动时调用所有契约的执行逻辑)
public bool Warmup { get; set; } = true;
// 遇到错误时是否抛异常
public bool ThrowOnError { get; set; } = true;
// 启动错误是否退出进程
public bool ExitOnError { get; set; } = false;
// 是否生成 JSON 诊断报告
public bool GenerateJsonReport { get; set; } = true;
// 应用程序 ID(诊断报告中使用)
public string? AppId { get; set; }
// 环境名称
public string? Environment { get; set; }
// 错误报告保存路径
public string? ErrorReportPath { get; set; }
// 自定义命名策略(用于投影器)
public INamingPolicy? NamingPolicy { get; set; }
// 加密器(warmup 测试用)
public IEncryptor? Encryptor { get; set; }
// 解密器(warmup 测试用)
public IDecryptor? Decryptor { get; set; }
}
NexusMirrorHostingExtensions
实现零反射的端点映射引擎。
路由模式:
{baseRoute}/{provider}/{profileId}/{operation...}
示例:
POST /api/alipay/{profileId}/trade/createGET /api/alipay/{profileId}/trade/queryPUT /api/wechat/{profileId}/merchant/modify
工作流程:
启动期(一次性):
1. 从元数据注册表获取所有契约元数据
2. 为每个契约类型预编译构造函数(宪法 007 合规)
3. 缓存方法调用器(MethodInvokerCache)
热路径(零反射):
1. 从路由参数提取 profileId
2. 从 HTTP Body 反序列化请求对象
3. 使用预编译构造函数创建实例(~10-20ns)
4. 调用 MethodInvokerCache(~100-200ns)
5. 序列化响应并返回
2. 安全模块(Security)
AesSecurityProvider
高性能的 AES256-CBC 对称加密提供程序。
算法规格:
| 参数 | 值 |
|---|---|
| 加密算法 | AES256-CBC |
| 密钥长度 | 256 位(32 字节) |
| 初始化向量 | 随机生成(16 字节) |
| 填充模式 | PKCS7 |
| 编码格式 | Base64 |
| 硬件加速 | CPU AES-NI 指令集 |
性能指标:
- 加密耗时:~5μs(2KB 密钥)
- 对比网络 IO:1ms Redis 延迟 >> 5μs 加密
- 热路径无额外开销(宪法 012 合规)
使用示例:
// 初始化加密器
var masterKeyBase64 = Convert.ToBase64String(
System.Security.Cryptography.RandomNumberGenerator.GetBytes(32));
var provider = new AesSecurityProvider(masterKeyBase64);
// 加密敏感数据
string encrypted = provider.Protect("my-private-key");
// 输出: "ECkR7Yj8n2m...(Base64 格式)"
// 解密数据
string decrypted = provider.Unprotect(encrypted);
// 输出: "my-private-key"
加密格式:
Base64([IV(16字节)][密文])
│
├─ IV:每次加密随机生成(防止模式攻击)
└─ 密文:AES256-CBC 加密结果
安全约束:
- 主密钥来源:环境变量
NEXUS_MASTER_KEY(Base64 编码的 32 字节) - 单一标准:所有加密数据统一为 Base64 编码的 [IV+密文]
- 密钥升级:通过运维脚本完成数据迁移(代码不参与版本判断)
生成主密钥:
# Linux/macOS
openssl rand -base64 32
# PowerShell
[Convert]::ToBase64String([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32))
ProtectedPrivateKeyConverter
JSON 序列化时的透明加密/解密转换器。
使用场景:
HybridConfigResolver将配置序列化到 RedisProviderSettings.PrivateKey字段保护
工作原理:
// 写入 Redis(序列化):明文 → AES256 加密 → Base64
[JsonPropertyName("privateKey")]
[JsonConverter(typeof(ProtectedPrivateKeyConverter))]
public string PrivateKey { get; set; } = "my-private-key";
// 从 Redis 读取(反序列化):Base64 → AES256 解密 → 明文
安全保障:
| 位置 | 存储内容 | 说明 |
|---|---|---|
| Redis | 密文(Base64) | 即使 Redis 泄露也无法直接使用 |
| 内存 L1 | 明文 | 避免每次签名都解密 |
| 传输 | TLS 加密 | Redis 连接使用 TLS |
API 文档
快速注册
// 最简用法
builder.Services.AddNexusContracts(opt =>
opt.ScanAssemblyContaining<TradeCreateRequest>());
// 完整配置
builder.Services.AddNexusContracts(options =>
{
options
.ScanAssemblies(typeof(TradeCreateRequest).Assembly)
.ScanAssemblies(typeof(MerchantApplyRequest).Assembly);
options.Warmup = true;
options.AppId = "my-app";
options.Environment = "Production";
options.GenerateJsonReport = true;
options.ErrorReportPath = "logs/contract-errors.json";
});
端点映射
// 使用默认基础路由 "/api"
app.MapNexusEndpoints();
// 使用自定义基础路由
app.MapNexusEndpoints("/v3");
// 多个服务可以使用不同的路由前缀
app.MapNexusEndpoints("/api/v1");
app.MapNexusEndpoints("/open");
使用安全提供程序
// 在 DI 容器中注册
builder.Services.AddSingleton<ISecretProtector>(
new AesSecurityProvider(masterKeyBase64));
// 在其他服务中注入使用
public class ConfigService
{
private readonly ISecretProtector _protector;
public ConfigService(ISecretProtector protector)
{
_protector = protector;
}
public void SaveConfig(ProviderSettings settings)
{
// 保护敏感字段
var protected = _protector.Protect(settings.PrivateKey);
RedisClient.Set("config", protected);
}
}
诊断报告
自动生成
启动时如果 GenerateJsonReport = true,系统自动生成诊断报告:
{
"appId": "alipay-gateway",
"environment": "Production",
"timestamp": "2025-01-18T08:17:00Z",
"summary": {
"totalContracts": 20,
"successCount": 20,
"failureCount": 0,
"criticalErrors": 0
},
"contracts": [
{
"name": "TradeCreateRequest",
"operationId": "alipay.trade.create",
"status": "success"
}
]
}
错误处理
如果发现错误,系统会:
- 打印详细的错误信息到控制台
- 保存 JSON 报告到
contract-errors.json - 根据
ThrowOnError/ExitOnError决定是否中止启动
❌ 契约验证失败:
失败契约数:2
错误总数:5(3 个致命错误)
❌ 系统启动已阻断,请修复上述错误后重试。
与其他模块的关系
架构层次
┌─────────────────────────────────────────┐
│ NexusContract.Hosting (你在这里) │
│ ASP.NET Core 集成 / 端点镜像 / 安全 │
├─────────────────────────────────────────┤
│ NexusContract.Core │
│ 执行引擎 / 路由元数据 / 诊断 │
├─────────────────────────────────────────┤
│ NexusContract.Abstractions │
│ 接口 / 属性 / 异常 / 安全契约 │
└─────────────────────────────────────────┘
与 NexusContract.Core 的关系
NexusContract.Hosting 依赖 NexusContract.Core 的核心组件:
| 组件 | 用途 |
|---|---|
INexusEngine |
合约执行引擎 |
NexusContractMetadataRegistry |
元数据注册表 |
ContractStartupHealthCheck |
启动检查 |
EndpointRouteMetadataBuilder |
路由元数据生成 |
MethodInvokerCache |
方法调用优化 |
与 NexusContract.Abstractions 的关系
使用抽象层的接口和属性:
| 接口/属性 | 说明 |
|---|---|
[ApiOperation] |
契约标记 |
IApiRequest<T> |
请求契约 |
ISecretProtector |
安全契约 |
INamingPolicy |
命名策略 |
ContractIncompleteException |
契约异常 |
性能优化
启动期优化
- 一次性编译:预编译构造函数(~10-20ns vs 200-500ns)
- 方法缓存:MethodInvokerCache 避免反射(~100-200ns vs 500-1000ns)
- 路由预生成:所有路由在启动期生成,热路径无计算
热路径优化
// 宪法 007 合规:零反射
var instance = constructorFactory(); // 预编译,~10-20ns
// 宪法 008 合规:直接调用
await MethodInvokerCache.InvokeExecuteAsync(
engine, requestObj, responseType, providerName, profileId, ct); // ~100-200ns
// 序列化直接转发
await JsonSerializer.SerializeAsync(context.Response.Body, result); // 无额外开销
最佳实践
1. 环境变量管理
# .env 或系统环境变量
export NEXUS_MASTER_KEY="base64-encoded-32-bytes"
# appsettings.json
{
"Logging": {...},
"NexusContract": {
"AppId": "my-gateway",
"Environment": "Production"
}
}
2. 错误处理
try
{
builder.Services.AddNexusContracts(options =>
{
options.ScanAssemblyContaining<MyContract>();
options.ThrowOnError = true; // 生产环境推荐
});
}
catch (ContractIncompleteException ex)
{
// 处理契约错误
logger.LogError($"Contract validation failed: {ex.Message}");
// 可选:保存诊断报告供分析
}
3. 多程序集扫描
builder.Services.AddNexusContracts(options =>
{
// 分别扫描不同的合约程序集
options.ScanAssemblyContaining<AlipayContracts>();
options.ScanAssemblyContaining<WechatContracts>();
options.ScanAssemblyContaining<UnionpayContracts>();
});
4. 自定义命名策略
public class SnakeCaseNamingPolicy : INamingPolicy
{
public string GetPropertyName(string clrName)
{
// 转换为 snake_case
return string.Concat(clrName.Select((x, i) =>
i > 0 && char.IsUpper(x) ? "_" + char.ToLower(x) : x.ToString())).ToLower();
}
}
builder.Services.AddNexusContracts(options =>
{
options.NamingPolicy = new SnakeCaseNamingPolicy();
});
故障排查
问题:缺少契约
⚠️ No contract metadata found. Did you forget to call builder.Services.AddNexusContracts()?
解决:确保在 Program.cs 中调用 AddNexusContracts()
问题:端点注册失败
❌ Failed to register TradeCreateRequest: Contract type does not implement IApiRequest<T>
解决:检查契约类是否继承了 IApiRequest<TResponse>
问题:主密钥错误
ArgumentException: Invalid master key: expected Base64-encoded 32-byte key
解决:生成正确的主密钥
openssl rand -base64 32
问题:性能下降
- 检查是否在热路径中重复编译构造函数
- 验证 MethodInvokerCache 是否正确初始化
- 查看是否存在意外的反射调用
宪法依据
本模块遵循以下宪法约束:
| 宪法 | 约束 | 实现 |
|---|---|---|
| 007 | 零反射热路径 | 预编译构造函数 + MethodInvokerCache |
| 008 | 性能隔离 | 启动期优化 / 热路径无额外开销 |
| 011 | 单一标准加密 | AES256-CBC + Base64 编码 |
| 012 | 诊断主权 | 结构化异常 + 诊断报告 |
相关资源
许可证
MIT License - 详见 LICENSE
维护者:NexusContract Team
最后更新:2025 年 1 月 18 日
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- NexusContract.Core (>= 1.0.0-preview.19)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|
v1.0: Contract auto-mirroring from NexusContractMetadataRegistry. Zero-code endpoint generation with physical routing. Removed dependency on FastEndpoints.