Bitzsoft.Integrations.AI.AspNetCore
1.1.0
dotnet add package Bitzsoft.Integrations.AI.AspNetCore --version 1.1.0
NuGet\Install-Package Bitzsoft.Integrations.AI.AspNetCore -Version 1.1.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Bitzsoft.Integrations.AI.AspNetCore" Version="1.1.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Bitzsoft.Integrations.AI.AspNetCore" Version="1.1.0" />
<PackageReference Include="Bitzsoft.Integrations.AI.AspNetCore" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Bitzsoft.Integrations.AI.AspNetCore --version 1.1.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: Bitzsoft.Integrations.AI.AspNetCore, 1.1.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Bitzsoft.Integrations.AI.AspNetCore@1.1.0
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Bitzsoft.Integrations.AI.AspNetCore&version=1.1.0
#tool nuget:?package=Bitzsoft.Integrations.AI.AspNetCore&version=1.1.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Bitzsoft.Integrations.AI.AspNetCore
面向企业多租户 ASP.NET Core AI 宿主的零 ORM 依赖、原生 AOT 兼容 HTTP 传输、错误治理与全业务端点辅助库。统一封装 SSE / NDJSON 零缓冲流式写出、RFC 9457 问题详情脱敏映射、已认证调用者租户 Fail-Closed 绑定、对话/后台长任务/多模态(STT/TTS/图像)Minimal API 与控制器辅助,以及面向存量 MVC 控制器的显式反射候选工具发现承接包。
版本与兼容性
dotnet add package Bitzsoft.Integrations.AI.AspNetCore
- 目标框架:
net8.0;net10.0; - 项目依赖:
Bitzsoft.Integrations.AI.Abstractions、Bitzsoft.Integrations.AI.Conversation、Bitzsoft.Integrations.McpServer; - 框架依赖:
FrameworkReference Include="Microsoft.AspNetCore.App"; - 原生 AOT 策略:工程启用
<IsAotCompatible>true</IsAotCompatible>,核心链路全量采用AIAspNetCoreJsonContext源生成序列化与零反射RequestDelegate;仅存量 MVC 反射扫描扩展类显式标注[RequiresUnreferencedCode]与[RequiresDynamicCode],不干扰纯原生 AOT 宿主零 IL 警告交付。
核心模块与设计边界
| 模块 | 核心类型与扩展 | 工程能力与安全边界 |
|---|---|---|
| A. 原生 AOT 源生成序列化上下文 | AIAspNetCoreJsonContext(.Default / .Relaxed) |
为 AIStreamFrame、BitzAIProblemDetailsResponse、BitzAICallerContext、后台长任务及 STT/TTS/图像强类型契约生成零反射 JSON 元数据,.Relaxed 开启中文非转义、camelCase 与忽略 null 字段 |
| B. RFC 9457 异常映射与统一中间件 | BitzAIProblemDetailsMapper、MapToProblemDetails、UseBitzAIExceptionHandler |
统一将 IAIDomainException(SuggestedHttpStatusCode、ErrorCode、IsRetryable、RetryAfter、TraceId)、IntegrationException、AIStreamIdleTimeoutException 与运行时异常映射为脱敏 application/problem+json;自动写出 Retry-After 与 X-Error-Code 响应头并剔除密钥与本机路径 |
| C. 租户与用户安全上下文绑定器 | BitzAICallerHttpContextResolver、IBitzAICallerHttpContextResolver、BitzAICallerContext |
严格仅从已认证 ClaimsPrincipal 声明(及 McpInProcessContextScope)解析 TenantId、UserId、角色与权限,彻底免疫 X-Tenant-Id / X-User-Id 请求头伪造,缺省身份或租户即 Fail-Closed 抛出 401/403 AIDomainException |
| D. 零缓冲流式写出器与状态帧扩展 | IAIStreamResponseWriter、AIStreamResponseWriter、AIStreamResponseWriterExtensions |
禁用响应缓冲并按帧即时 FlushAsync 输出 SSE / NDJSON;WriteStreamWithPrefetchAsync 支持首帧异常前切回 RFC 9457 错误响应;提供 CreateHitlApprovalFrame、CreateHitlSuspendedFrame、CreateDryRunPreviewFrame、CreateContinuationStatusFrame 与 CreateFinOpsUsageFrame 辅助 |
| E. 对话、后台任务与多模态端点辅助 | BitzAIConversationEndpointHelper、BitzAIBackgroundJobEndpointHelper、BitzAIMultimodalEndpointHelper |
统一复用调用者绑定与 RFC 9457 错误出口:ExecuteOrchestratedTurnStreamAsync 自动压入 McpInProcessContextScope;MapBitzAIBackgroundJobEndpoints 提供 GET /{jobId} 与 POST /{jobId}/cancel 并校验租户/用户归属;MapBitzAIMultimodalEndpoints 覆盖 /stt、/stt/stream、/tts、/tts/audio 与 /images;FetchSafeRemoteImageBytesAsync 提供公网 IP / DNS 重绑定 ConnectCallback、最多 3 跳手动重定向、字节上限与光栅魔数校验 |
| F. MVC 控制器只读反射发现(非 AOT 可选) | McpMvcCandidateDiscoverySource、AddBitzMcpMvcCandidateDiscovery、McpActionReadOnlyClassifier、McpControllerActionToolBuilder |
从 McpServer 剥离下沉 ASP.NET MVC 反射依赖,对接 IMcpCandidateDiscoverySource 与 McpInProcessContextScope.Push;每次调用创建并释放独立 AsyncServiceScope,请求头按安全白名单与身份前缀阻断转发,提供 ResolveReadOnlyActionMethod / BindActionParameters(含值类型 DTO);无权限注解候选默认拒绝(SuggestedPermissionCodes == null),反射入口均显式标注 [RequiresUnreferencedCode] / [RequiresDynamicCode] |
一站式装配与异常中间件
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddBitzsoftAIAspNetCore(
configureStreamWriter: o => o.DefaultFormat = AIStreamFormat.Sse,
configureCallerResolution: o => o.AllowFallbackTenantZero = false,
configureProblemDetails: o => o.IncludeExceptionDetails = builder.Environment.IsDevelopment());
// 若存量 MVC 宿主需自动扫描只读控制器动作作为 MCP 候选工具(非 AOT 场景):
// builder.Services.AddBitzMcpGovernanceCore();
// builder.Services.AddBitzMcpMvcCandidateDiscovery();
var app = builder.Build();
app.UseBitzAIExceptionHandler();
app.MapBitzAIBackgroundJobEndpoints("/api/ai/jobs").RequireAuthorization();
app.MapBitzAIMultimodalEndpoints("/api/ai/multimodal").RequireAuthorization();
完整最小示例
以下独立示例演示注入 ASP.NET Core AI 传输层服务、映射 AIDomainException 为脱敏 RFC 9457 详情、绑定已认证 HTTP 调用者上下文,以及零缓冲输出 HITL 审批、FDE 试运行预览与 FinOps 用量帧:
using System.Security.Claims;
using System.Text;
using System.Text.Json;
using Bitzsoft.Integrations.AI.Abstractions;
using Bitzsoft.Integrations.AI.AspNetCore;
using Bitzsoft.Integrations.AI.Conversation;
using Bitzsoft.Integrations.AI.Governance;
using Bitzsoft.Integrations.Core;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
services.AddBitzsoftAIAspNetCore();
await using ServiceProvider provider = services.BuildServiceProvider(
new ServiceProviderOptions { ValidateOnBuild = true, ValidateScopes = true });
// 1. 解析并 Fail-Closed 校验已认证调用者租户与身份(免疫 X-Tenant-Id 请求头伪造)。
var httpContext = new DefaultHttpContext
{
RequestServices = provider,
TraceIdentifier = "trace-demo-01",
User = new ClaimsPrincipal(new ClaimsIdentity(
[
new Claim(ClaimTypes.NameIdentifier, "lawyer-1001"),
new Claim("TenantId", "tenant-sh-01"),
new Claim("permission", "contracts:review"),
], "Bearer")),
};
httpContext.Request.Headers["X-Tenant-Id"] = "attacker-tenant";
var callerResolver = provider.GetRequiredService<IBitzAICallerHttpContextResolver>();
BitzAICallerContext caller = callerResolver.Resolve(httpContext);
// 2. 将领域异常统一映射为脱敏 RFC 9457 响应模型(支持 RetryAfter 与 TraceId)。
var problemMapper = provider.GetRequiredService<BitzAIProblemDetailsMapper>();
var rateLimitEx = new AIDomainException(
errorCode: AIExecutionErrorCodes.RateLimited,
message: "上游模型限流,请退避后重试",
suggestedHttpStatusCode: StatusCodes.Status429TooManyRequests,
provider: "deepseek",
failureKind: IntegrationFailureKind.RateLimited,
isRetryable: true,
retryAfter: TimeSpan.FromSeconds(10));
BitzAIProblemDetailsResponse problem = problemMapper.MapToResponse(rateLimitEx, httpContext);
// 3. 构造 HITL 挂起、DryRun 试运行预览与 FinOps 计费终结帧并零缓冲写出 SSE。
var checkpoint = new AIHitlCheckpointState(
PendingActionId: "act-demo-1",
TenantId: caller.TenantId,
UserId: caller.UserId,
SessionId: "sess-demo-1",
RequestId: "req-demo-1",
TurnId: "turn-1",
AgentCode: "contract-agent",
ToolCallId: "call-1",
ToolName: "seal_contract",
ArgumentsJson: """{"contractId":"c-01"}""",
ArgumentsHash: "hash-c01",
SuspendedStateJson: null,
Status: AIHitlSuspendStatus.Suspended,
CreatedAt: DateTimeOffset.UtcNow,
ExpiresAt: DateTimeOffset.UtcNow.AddMinutes(15));
AIStreamFrame[] frames =
[
AIStreamResponseWriterExtensions.CreateHitlApprovalFrame(checkpoint),
AIStreamResponseWriterExtensions.CreateDryRunPreviewFrame("call-2", "update_status", wouldMutate: true, message: "预览:将更新 1 条记录"),
AIStreamResponseWriterExtensions.CreateFinOpsUsageFrame(new AIFinOpsUsageRecord
{
TenantId = caller.TenantId,
UserId = caller.UserId,
SessionId = "sess-demo-1",
RequestId = "req-demo-1",
ModelId = "deepseek-chat",
InputTokens = 500,
OutputTokens = 120,
EstimatedCost = 0.0042m,
}),
];
await using var responseStream = new MemoryStream();
httpContext.Response.Body = responseStream;
var writer = provider.GetRequiredService<IAIStreamResponseWriter>();
await writer.WriteStreamWithPrefetchAsync(httpContext, ToAsyncFrames(frames), problemMapper, AIStreamFormat.Sse);
string sseOutput = Encoding.UTF8.GetString(responseStream.ToArray());
string problemJson = JsonSerializer.Serialize(problem, AIAspNetCoreJsonContext.Relaxed.BitzAIProblemDetailsResponse);
Console.WriteLine($"租户={caller.TenantId},错误码={problem.ErrorCode},SSE长度={sseOutput.Length},RFC9457={problemJson}");
static async IAsyncEnumerable<AIStreamFrame> ToAsyncFrames(AIStreamFrame[] items)
{
foreach (AIStreamFrame item in items)
{
yield return item;
await Task.Yield();
}
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. 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. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net10.0
- Bitzsoft.Integrations.AI.Abstractions (>= 1.1.0)
- Bitzsoft.Integrations.AI.Conversation (>= 1.1.0)
- Bitzsoft.Integrations.McpServer (>= 1.1.0)
-
net8.0
- Bitzsoft.Integrations.AI.Abstractions (>= 1.1.0)
- Bitzsoft.Integrations.AI.Conversation (>= 1.1.0)
- Bitzsoft.Integrations.McpServer (>= 1.1.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.