Token导航 LogoToken导航TokenDH.com
前端设计敏感数据github未标认证来源可访问许可证需确认审计通过

aspnet-core-apisaspnet 核心 API

Agent Skill

aspnet-core-apis 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

192

周安装

8

GitHub Stars

11

下载量

64
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:aspnet-core-apis(aspnet 核心 API)
来源仓库:https://github.com/lobbi-docs/claude
仓库路径:skills/aspnet-core-apis
安装命令:
npx skills add https://github.com/lobbi-docs/claude --skill aspnet-core-apis
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/lobbi-docs/claude --skill aspnet-core-apis

简介

aspnet-core-apis 专注于 ASP.NET Core Minimal APIs 的设计与实现模式。

  • 适用于构建轻量级 RESTful 接口,支持分组路由、参数绑定与强类型响应。
  • 它展示如何使用 MapGroup、WithTags 和 RequireAuthorization 组织端点逻辑。
  • 输出示例基于 .NET 10+ 特性,旧版本需降级至传统 Controller 模式实现类似功能。
  • 建议配合 Swagger/OpenAPI 工具链自动生成接口文档与客户端 SDK。

SKILL.md

ASP.NET Core API Development

Minimal APIs (.NET 10 Preferred)

Endpoint Groups

public static class ProductEndpoints
{
    public static RouteGroupBuilder MapProductEndpoints(this WebApplication app)
    {
        var group = app.MapGroup("/api/products")
            .WithTags("Products")
            .RequireAuthorization();

        group.MapGet("/", GetAll);
        group.MapGet("/{id:int}", GetById);
        group.MapPost("/", Create);
        group.MapPut("/{id:int}", Update);
        group.MapDelete("/{id:int}", Delete);

        return group;
    }

    private static async Task<IResult> GetAll(
        [AsParameters] ProductQuery query,
        IProductService service,
        CancellationToken ct) =>
        TypedResults.Ok(await service.GetAllAsync(query, ct));

    private static async Task<IResult> GetById(int id, IProductService service, CancellationToken ct) =>
        await service.GetByIdAsync(id, ct) is { } product
            ? TypedResults.Ok(product)
            : TypedResults.NotFound();
}

Program.cs Registration

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApi();
builder.Services.AddOutputCache();
builder.Services.AddRateLimiter(opts => opts.AddFixedWindowLimiter("api", o =>
{
    o.Window = TimeSpan.FromMinutes(1);
    o.PermitLimit = 100;
}));

var app = builder.Build();

app.UseOutputCache();
app.UseRateLimiter();
app.MapOpenApi();

app.MapProductEndpoints();
app.MapOrderEndpoints();

app.Run();

Middleware Pipeline

Request → UseExceptionHandler → UseHsts → UseHttpsRedirection
    → UseStaticFiles → UseRouting → UseCors → UseAuthentication
    → UseAuthorization → UseOutputCache → UseRateLimiter → Endpoints

Custom Middleware

public sealed class RequestTimingMiddleware(RequestDelegate next, ILogger<RequestTimingMiddleware> logger)
{
    public async Task InvokeAsync(HttpContext context)
    {
        var sw = Stopwatch.StartNew();
        try
        {
            await next(context);
        }
        finally
        {
            sw.Stop();
            logger.LogInformation("Request {Method} {Path} completed in {Elapsed}ms",
                context.Request.Method, context.Request.Path, sw.ElapsedMilliseconds);
        }
    }
}

// Register: app.UseMiddleware<RequestTimingMiddleware>();

Endpoint Filters

public sealed class ValidationFilter<T> : IEndpointFilter where T : class
{
    public async ValueTask<object?> InvokeAsync(
        EndpointFilterInvocationContext context,
        EndpointFilterDelegate next)
    {
        var validator = context.HttpContext.RequestServices.GetService<IValidator<T>>();
        if (validator is null) return await next(context);

        var model = context.GetArgument<T>(0);
        var result = await validator.ValidateAsync(model);

        return result.IsValid
            ? await next(context)
            : TypedResults.ValidationProblem(result.ToDictionary());
    }
}

OpenAPI / Swagger

// .NET 10 built-in OpenAPI
builder.Services.AddOpenApi(options =>
{
    options.AddDocumentTransformer((doc, ctx, ct) =>
    {
        doc.Info.Title = "My API";
        doc.Info.Version = "v1";
        return Task.CompletedTask;
    });
});

app.MapOpenApi(); // Serves at /openapi/v1.json
app.MapScalarApiReference(); // Interactive API explorer UI

Error Handling

// Global exception handler with Problem Details
builder.Services.AddProblemDetails();

app.UseExceptionHandler(error =>
{
    error.Run(async context =>
    {
        var exception = context.Features.Get<IExceptionHandlerFeature>()?.Error;
        var problem = exception switch
        {
            NotFoundException => new ProblemDetails
            {
                Status = 404, Title = "Not Found", Detail = exception.Message
            },
            ValidationException ve => new ProblemDetails
            {
                Status = 400, Title = "Validation Error",
                Extensions = { ["errors"] = ve.Errors }
            },
            _ => new ProblemDetails
            {
                Status = 500, Title = "Internal Server Error"
            }
        };

        context.Response.StatusCode = problem.Status ?? 500;
        await context.Response.WriteAsJsonAsync(problem);
    });
});

Rate Limiting (from official docs)

builder.Services.AddRateLimiter(options =>
{
    // Fixed Window - simple time-based limit
    options.AddFixedWindowLimiter("fixed", opt =>
    {
        opt.PermitLimit = 4;
        opt.Window = TimeSpan.FromSeconds(12);
        opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        opt.QueueLimit = 2;
    });

    // Sliding Window - smoother rate control
    options.AddSlidingWindowLimiter("sliding", opt =>
    {
        opt.PermitLimit = 100;
        opt.Window = TimeSpan.FromSeconds(30);
        opt.SegmentsPerWindow = 3;
    });

    // Token Bucket - burst-friendly
    options.AddTokenBucketLimiter("token", opt =>
    {
        opt.TokenLimit = 100;
        opt.ReplenishmentPeriod = TimeSpan.FromSeconds(10);
        opt.TokensPerPeriod = 20;
        opt.AutoReplenishment = true;
    });

    // Concurrency - limits concurrent requests, not rate
    options.AddConcurrencyLimiter("concurrency", opt =>
    {
        opt.PermitLimit = 50;
        opt.QueueLimit = 10;
    });

    // Custom rejection response
    options.OnRejected = async (context, ct) =>
    {
        context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
        if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
            context.HttpContext.Response.Headers.RetryAfter = ((int)retryAfter.TotalSeconds).ToString();
        await context.HttpContext.Response.WriteAsync("Rate limit exceeded.", ct);
    };
});

// IMPORTANT: UseRouting MUST come before UseRateLimiter for endpoint-specific limiters
app.UseRouting();
app.UseRateLimiter();

// Apply to endpoints
app.MapGet("/api/limited", () => "OK").RequireRateLimiting("fixed");

// Partitioned by API key with tiered limits
options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(context =>
{
    string apiKey = context.Request.Headers["X-API-Key"].ToString() ?? "default";
    return apiKey switch
    {
        "premium-key" => RateLimitPartition.GetFixedWindowLimiter(apiKey,
            _ => new FixedWindowRateLimiterOptions { PermitLimit = 1000, Window = TimeSpan.FromMinutes(1) }),
        _ => RateLimitPartition.GetFixedWindowLimiter(apiKey,
            _ => new FixedWindowRateLimiterOptions { PermitLimit = 100, Window = TimeSpan.FromMinutes(1) })
    };
});

Dependency Injection Patterns (from official docs)

// Lifetimes
builder.Services.AddTransient<ITransientService, TransientService>();  // New each time
builder.Services.AddScoped<IScopedService, ScopedService>();          // Per request
builder.Services.AddSingleton<ISingletonService, SingletonService>(); // Once

// Factory registration
builder.Services.AddScoped<IMyService>(sp =>
    new MyService(sp.GetRequiredService<IDependency>()));

// Keyed services (multiple implementations of same interface)
builder.Services.AddKeyedSingleton<ICache, RedisCache>("redis");
builder.Services.AddKeyedSingleton<ICache, MemoryCache>("memory");

// Inject keyed service in minimal API
app.MapGet("/data", ([FromKeyedServices("redis")] ICache cache) => cache.Get("key"));

// Extension method pattern for clean DI registration
public static class MyServiceExtensions
{
    public static IServiceCollection AddMyServices(this IServiceCollection services, IConfiguration config)
    {
        services.Configure<MyOptions>(config.GetSection("MyOptions"));
        services.AddScoped<IMyService, MyService>();
        return services;
    }
}

Middleware Pipeline Order (from official docs)

// Correct order for ASP.NET Core 10:
if (app.Environment.IsDevelopment())
    app.UseDeveloperExceptionPage();
else
    app.UseExceptionHandler("/Error", createScopeForErrors: true);

app.UseHttpsRedirection();
app.UseStaticFiles();       // or app.MapStaticAssets()
app.UseRouting();            // MUST come before rate limiter
app.UseRateLimiter();
app.UseCors();               // MUST come before auth and after routing
app.UseAuthentication();
app.UseAuthorization();
app.UseAntiforgery();        // After auth
app.UseResponseCaching();    // After CORS
app.UseResponseCompression();

// Endpoints last
app.MapRazorComponents<App>().AddInteractiveServerRenderMode();
app.MapControllers();

Native AOT Support

// Use CreateSlimBuilder for AOT-compatible apps
var builder = WebApplication.CreateSlimBuilder(args);

// JSON source generator required for AOT
builder.Services.ConfigureHttpJsonOptions(options =>
    options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default));

var app = builder.Build();
app.MapGet("/todos", () => new Todo(1, "Walk dog", false));
app.Run();

[JsonSerializable(typeof(Todo[]))]
[JsonSerializable(typeof(Todo))]
internal partial class AppJsonSerializerContext : JsonSerializerContext { }

public record Todo(int Id, string Title, bool IsComplete);
<!-- In .csproj for AOT publishing -->
<PublishAot>true</PublishAot>

Options Pattern (from official docs)

// Bind configuration to strongly-typed class
public sealed class SmtpOptions
{
    public const string SectionName = "Smtp";
    [Required] public string Host { get; set; } = "";
    [Range(1, 65535)] public int Port { get; set; } = 587;
    public string? Username { get; set; }
}

// Register with validation
builder.Services.AddOptions<SmtpOptions>()
    .BindConfiguration(SmtpOptions.SectionName)
    .ValidateDataAnnotations()  // Validates [Required], [Range], etc.
    .ValidateOnStart();          // Fail fast at startup if invalid

// Inject: IOptions<T> (singleton), IOptionsSnapshot<T> (scoped, reloads),
//         IOptionsMonitor<T> (singleton, notifies on change)
public sealed class EmailService(IOptions<SmtpOptions> options)
{
    private readonly SmtpOptions _smtp = options.Value;
}

Best Practices

  • Use TypedResults for compile-time response type checking
  • Always pass and respect CancellationToken
  • Use [AsParameters] for complex query objects
  • Group endpoints by feature/resource with MapGroup()
  • Use endpoint filters instead of controller action filters
  • Prefer IResult return type for all handlers
  • Add OpenAPI annotations for documentation
  • Use output caching for read-heavy endpoints
  • UseRouting MUST come before UseRateLimiter
  • CORS MUST come before UseResponseCaching
  • Use CreateSlimBuilder + JSON source generators for Native AOT
  • Use ValidateOnStart() with Options pattern to fail fast

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

36.24%
按下载量换算23

Claude

29.61%
按下载量换算19

Cursor

19.43%
按下载量换算12

Gemini CLI

8.17%
按下载量换算5

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills