mcpField
A
aspnet-core

aspnet-core

github.com/mindrally開発289791 回インストール3 週間前に更新
リポジトリ

aspnet-core について

ASP.NET Core の Web API 開発ガイドです。コントローラー設計、ミドルウェア、キャッシュ、認証、検証、設定、ドキュメントを扱います。

主な機能

  1. 01REST コントローラー設計の実践
  2. 02ミドルウェアの順序とカスタマイズ
  3. 03キャッシュと JWT 認証の指針
  4. 04認可と検証のパターン
  5. 05設定と Swagger/OpenAPI

活用シーン

  1. 01ASP.NET Core API の構成を設計
  2. 02JWT 認証とポリシーを実装
  3. 03入力検証とグローバルエラー処理を追加
  4. 04Swagger で API エンドポイントを文書化

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mindrally/skills --skill aspnet-core

インストール後、Claude Code で/aspnet-coreを入力して読み込まれたか確認します。

詳細

ASP.NET Core 開発ガイドライン

Web API 設計、認証、ミドルウェア、パフォーマンス最適化に関する深い知識を持つ、ASP.NET Core 開発のエキスパートです。

プロジェクト構成

src/
  Controllers/      # API endpoints
  Models/          # Domain models and DTOs
  Services/        # Business logic
  Data/            # DbContext and repositories
  Middleware/      # Custom middleware
  Extensions/      # Extension methods
  Configuration/   # App configuration
Program.cs
appsettings.json

コントローラーの設計

RESTful コントローラー
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
    private readonly IProductService _productService;

    public ProductsController(IProductService productService)
    {
        _productService = productService;
    }

    [HttpGet]
    public async Task<ActionResult<IEnumerable<ProductDto>>> GetProducts()
    {
        var products = await _productService.GetAllAsync();
        return Ok(products);
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<ProductDto>> GetProduct(int id)
    {
        var product = await _productService.GetByIdAsync(id);
        if (product == null)
            return NotFound();
        return Ok(product);
    }

    [HttpPost]
    public async Task<ActionResult<ProductDto>> CreateProduct(CreateProductDto dto)
    {
        var product = await _productService.CreateAsync(dto);
        return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
    }
}
ベストプラクティス
  • コントローラーは薄く保ちます
  • リクエストとレスポンスには DTO を使用します
  • 適切なステータスコードを返します
  • 一貫して async/await を使用します
  • 適切なバリデーションを実装します

ミドルウェア

カスタムミドルウェア
public class RequestLoggingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<RequestLoggingMiddleware> _logger;

    public RequestLoggingMiddleware(RequestDelegate next, ILogger<RequestLoggingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        _logger.LogInformation("Request: {Method} {Path}", context.Request.Method, context.Request.Path);
        await _next(context);
        _logger.LogInformation("Response: {StatusCode}", context.Response.StatusCode);
    }
}
ミドルウェアの順序
  1. 例外処理
  2. HTTPS リダイレクト
  3. 静的ファイル
  4. ルーティング
  5. CORS
  6. 認証
  7. 認可
  8. カスタムミドルウェア
  9. エンドポイント

キャッシュ

レスポンスキャッシュ
[HttpGet]
[ResponseCache(Duration = 60)]
public async Task<ActionResult<IEnumerable<ProductDto>>> GetProducts()
メモリキャッシュ
public class ProductService : IProductService
{
    private readonly IMemoryCache _cache;

    public async Task<Product?> GetByIdAsync(int id)
    {
        return await _cache.GetOrCreateAsync($"product_{id}", async entry =>
        {
            entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10);
            return await _repository.GetByIdAsync(id);
        });
    }
}
分散キャッシュ
  • 複数サーバーのシナリオでは Redis を使用します
  • Program.cs で設定します
  • IDistributedCache インターフェイスを使用します

認証

JWT の設定
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(
                Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!))
        };
    });
トークン生成
public string GenerateToken(User user)
{
    var claims = new[]
    {
        new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
        new Claim(ClaimTypes.Email, user.Email),
        new Claim(ClaimTypes.Role, user.Role)
    };

    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]!));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

    var token = new JwtSecurityToken(
        issuer: _config["Jwt:Issuer"],
        audience: _config["Jwt:Audience"],
        claims: claims,
        expires: DateTime.UtcNow.AddHours(1),
        signingCredentials: creds);

    return new JwtSecurityTokenHandler().WriteToken(token);
}

認可

ポリシーベースの認可
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"));
    options.AddPolicy("PremiumUser", policy => policy.RequireClaim("Subscription", "Premium"));
});

[Authorize(Policy = "AdminOnly")]
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteProduct(int id)

エラー処理

グローバル例外ハンドラー
app.UseExceptionHandler(errorApp =>
{
    errorApp.Run(async context =>
    {
        context.Response.StatusCode = 500;
        context.Response.ContentType = "application/json";

        var error = context.Features.Get<IExceptionHandlerFeature>();
        if (error != null)
        {
            await context.Response.WriteAsJsonAsync(new
            {
                error = "An error occurred",
                detail = app.Environment.IsDevelopment() ? error.Error.Message : null
            });
        }
    });
});

バリデーション

FluentValidation
public class CreateProductValidator : AbstractValidator<CreateProductDto>
{
    public CreateProductValidator()
    {
        RuleFor(x => x.Name).NotEmpty().MaximumLength(100);
        RuleFor(x => x.Price).GreaterThan(0);
        RuleFor(x => x.Category).NotEmpty();
    }
}

構成

Options パターン
builder.Services.Configure<SmtpSettings>(builder.Configuration.GetSection("Smtp"));

public class EmailService
{
    private readonly SmtpSettings _settings;

    public EmailService(IOptions<SmtpSettings> options)
    {
        _settings = options.Value;
    }
}

ドキュメント

Swagger/OpenAPI
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Type = SecuritySchemeType.Http,
        Scheme = "bearer",
        BearerFormat = "JWT"
    });
});

コメント