plugins/languages/csharp/skills/web/SKILL.md
ASP.NET Core 10 Web 开发规范。覆盖 Minimal API、native AOT 发布、Blazor SSR / Streaming / Auto / Interactive 渲染模式、rate limiting、output caching、HybridCache、 middleware 顺序、IExceptionHandler + ProblemDetails、OpenAPI 3.1、健康检查、 JWT / Identity API、WebApplicationFactory 集成测试。 当开发 Web API、REST 服务、Blazor 应用、配置中间件管道、调优 ASP.NET Core, 或说 "ASP.NET Core"、"Minimal API"、"Blazor"、"middleware"、"WebApplication"、 "AOT publish"、"HybridCache" 时加载。
npx skillsauth add lazygophers/ccplugin csharp-webInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
主流形态: Minimal API + EF Core + Blazor SSR。
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddProblemDetails()
.AddOpenApi() // .NET 9+ 内置 (替代 Swashbuckle)
.AddOutputCache()
.AddHybridCache() // .NET 10 GA, 替代 IDistributedCache
.AddExceptionHandler<GlobalExceptionHandler>()
.AddRateLimiter(o => o.AddFixedWindowLimiter("api", w =>
{
w.PermitLimit = 100;
w.Window = TimeSpan.FromMinutes(1);
}))
.AddAuthentication().AddJwtBearer();
builder.Services.AddDbContextPool<AppDb>(o =>
o.UseNpgsql(builder.Configuration.GetConnectionString("Db")));
var app = builder.Build();
app.UseExceptionHandler(); // 早期捕获
app.UseStatusCodePages();
app.UseHttpsRedirection();
app.UseRateLimiter();
app.UseAuthentication();
app.UseAuthorization();
app.UseOutputCache();
app.MapOpenApi();
app.MapHealthChecks("/health");
app.MapOrders(); // 扩展方法分组 endpoint
app.Run();
public partial class Program; // 让集成测试可见
每个资源一个静态类, 扩展方法 + MapGroup:
public static class OrderEndpoints
{
public static IEndpointRouteBuilder MapOrders(this IEndpointRouteBuilder app)
{
var g = app.MapGroup("/api/orders")
.RequireAuthorization()
.RequireRateLimiting("api")
.WithTags("orders");
g.MapGet("/{id:long}", GetById).WithName("GetOrder").CacheOutput();
g.MapPost("/", Create).AddEndpointFilter<ValidationFilter>();
return app;
}
static async Task<Results<Ok<OrderDto>, NotFound>> GetById(
long id, IOrderService svc, CancellationToken ct) =>
await svc.FindAsync(id, ct) is { } o ? TypedResults.Ok(o) : TypedResults.NotFound();
}
Results<T1, T2> / TypedResults.* 让 OpenAPI 推断准确Results.Ok (非类型化), 用 TypedResults.Ok[FromBody] / [FromQuery] / [FromServices] / [AsParameters]public class GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger) : IExceptionHandler
{
public async ValueTask<bool> TryHandleAsync(
HttpContext ctx, Exception ex, CancellationToken ct)
{
logger.LogError(ex, "Unhandled: {Message}", ex.Message);
await Results.Problem(
title: "Internal Server Error",
statusCode: StatusCodes.Status500InternalServerError,
extensions: new Dictionary<string, object?> { ["traceId"] = ctx.TraceIdentifier })
.ExecuteAsync(ctx);
return true;
}
}
业务错误: endpoint 直接返回 TypedResults.Problem(...) / ValidationProblem。
record + required + 数据注解; 复杂规则用 Microsoft.AspNetCore.Http.Validation (.NET 10 内置) 或 FluentValidationAddProblemDetails)<PublishAot>true</PublishAot>
要求:
Newtonsoft.Json; 用 System.Text.Json source generatordotnet publish -c Release 检查 IL2026 / IL3050 警告[JsonSerializable(typeof(OrderDto))]
[JsonSerializable(typeof(CreateOrderDto))]
internal partial class AppJsonContext : JsonSerializerContext;
builder.Services.ConfigureHttpJsonOptions(o =>
o.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonContext.Default));
| 模式 | 何时用 |
|------|--------|
| Static SSR | 列表/详情页面, 纯展示 |
| SSR Streaming ([StreamRendering]) | 大段数据分块渲染 |
| Interactive Server | 内网工具, 状态在服务端 |
| Interactive WebAssembly | 高交互、可离线 |
| Auto | SSR 首屏 + WebAssembly 接管 |
组件以 @rendermode 显式声明; 不要全站默认 Interactive。
固定顺序: Exception → HTTPS → Static → Routing → CORS → AuthN → AuthZ → RateLimiter → OutputCache → Endpoints。
自定义中间件继承 IMiddleware (DI 友好) 而不是约定方法。
AddJwtBearer; Authority + Audience 必填IAuthorizationHandler + OperationAuthorizationRequirementUser.HasClaim, 用 policyAddIdentityApiEndpoints<T>() 提供注册/登录/MFA 全套 endpointCacheOutput(...)IDistributedCachevar u = await cache.GetOrCreateAsync($"user:{id}",
async ct => await db.Users.FindAsync([id], ct),
tags: ["users"]);
AddOpenTelemetry().WithTracing().WithMetrics().WithLogs()Microsoft.AspNetCore.Hosting、Microsoft.AspNetCore.Server.KestrelWebApplicationFactory<Program>; Program 加 public partial class Program;WithWebHostBuilder + ConfigureTestServicestools
UI/UX 与布局设计——做界面布局/结构/导航/组件/交互的设计决策。触发:做UI/UX/布局/排版/导航/组件/交互/栅格/响应式/图表选型/字体配对。按媒介路由 HTML/Web、原生 App(iOS/Android/桌面)、CLI、TUI。需后端动态系统不适用;配色/主题/色板走姊妹 skill design-color。
tools
主题与配色设计——做颜色搭配/调色板/主题/品牌色阶/暗模式的设计决策。触发:选配色/调色/主题/色板/品牌色/暗模式/对比度/色盲/UI风格。按媒介路由 HTML/Web(CSS变量)、原生App(平台token)、CLI(ANSI)、TUI(真彩/256/16降级)。保证可访问性(对比度/色盲安全)。需后端动态系统不适用;UI/UX 布局/组件/交互走姊妹 skill design-uiux。
tools
跨任意组件(plugin/skill/agent/command)的验证驱动优化循环纪律 skill。当用户要优化某个已有组件却无明确方向、或要防止改了反而更差(自评乐观偏差 / 多维同改归因失效 / 为凑分加废话膨胀)、或要把一套通用「评分→单变量改→改后验证严格更好才留否则回滚→触顶停」的纪律套到任意组件上时使用。管优化过程本身的纪律(validation gate / ratchet / 独立验证 / 触顶停),不评单组件深度(交 skill-dev),不查插件接线(交 plugin-dev)。仅手动 /optimize-any 触发。
data-ai
两层规则记忆 (基于 .skein/spec)。planning 时 recall 召回相关规则、task finish 后 sediment 沉淀学习 + prune 自动精简过期/重复/断链规则。core 常驻硬规 + recall 按需召回, 经判定门自动写盘 (不逐次问用户)。产出 .skein/spec 下 core/recall 规则文件 + index。另支持空仓 bootstrap 播种规则基线、记忆大面积失效 (大重构/换栈) 时 reconstruct 可逆归档后按项目类型分型重建、maintain 手动体检 (超预算/stale/断链/重复/废弃, --apply 自动修复)、auto-fix (Stop hook 写 .pending-fix 标记 → main 派 skein-specer bg 跑 maintain --apply 全自动修, 断链只报告)。