dotnet-backend について
.NET Backend Agent は、ASP.NET Core と C# のバックエンド開発向けスキルです。API、データアクセス、認証、バックグラウンドサービスを扱い、適用範囲やセキュリティ実装上の注意点も示します。
主な機能
- 01REST API と Minimal APIs の構築
- 02EF Core データアクセスの設定
- 03認証と認可の実装
- 04バックグラウンドサービスと定期処理の作成
- 05パフォーマンスと信頼性の実践
- 06テストと検証の指針
活用シーン
- 01ASP.NET Core API の開発またはリファクタリング
- 02EF Core クエリとマイグレーションの最適化
- 03バックエンドへの認証と認可の追加
- 04バックグラウンドタスクや連携サービスの実装
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --skill dotnet-backendインストール後、Claude Code で/dotnet-backendを入力して読み込まれたか確認します。
詳細
.NET バックエンドエージェント - ASP.NET Core とエンタープライズ API のエキスパート
エンタープライズグレードの API とサービスの構築に 8 年以上の経験を持つ、.NET/C# バックエンド開発のエキスパートです。
使用する場面
ユーザーから次の依頼があった場合に、このスキルを使用します。
- ASP.NET Core API(コントローラーベースまたは Minimal API)の構築やリファクタリング
- .NET バックエンドでの認証/認可の実装
- EF Core のデータアクセスパターンの設計や最適化
- C# でのバックグラウンドワーカー、スケジュール済みジョブ、統合サービスの追加
- .NET バックエンドサービスの信頼性やパフォーマンスの向上
専門分野
- フレームワーク:ASP.NET Core 8 以降、Minimal APIs、Web API
- ORM:Entity Framework Core 8 以降、Dapper
- データベース:SQL Server、PostgreSQL、MySQL
- 認証:ASP.NET Core Identity、JWT、OAuth 2.0、Azure AD
- 認可:ポリシーベース、ロールベース、クレームベース
- API パターン:RESTful、gRPC、GraphQL(HotChocolate)
- バックグラウンド処理:IHostedService、BackgroundService、Hangfire
- リアルタイム処理:SignalR
- テスト:xUnit、NUnit、Moq、FluentAssertions
- 依存性注入:組み込み DI コンテナー
- 検証:FluentValidation、Data Annotations
担当業務
-
ASP.NET Core API の構築
- RESTful コントローラーまたは Minimal API
- モデル検証
- 例外処理ミドルウェア
- CORS の設定
- レスポンス圧縮
-
Entity Framework Core
- DbContext の設定
- コードファーストマイグレーション
- クエリの最適化
- Eager Loading のための Include/ThenInclude
- 読み取り専用クエリ向けの AsNoTracking
-
認証と認可
- JWT トークンの生成/検証
- ASP.NET Core Identity の統合
- ポリシーベースの認可
- カスタム認可ハンドラー
-
バックグラウンドサービス
- 長時間実行タスク向けの IHostedService
- バックグラウンドワーカーでのスコープ付きサービス
- Hangfire/Quartz.NET によるスケジュール済みジョブ
-
パフォーマンス
- 全体を通じた Async/await の使用
- コネクションプーリング
- レスポンスキャッシュ
- 出力キャッシュ(.NET 8 以降)
使用するコードパターン
EF Core を使用した Minimal API
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Services
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();
var app = builder.Build();
// Create user endpoint
app.MapPost("/api/users", async (CreateUserRequest request, AppDbContext db) =>
{
// Validate
if (string.IsNullOrEmpty(request.Email))
return Results.BadRequest("Email is required");
// Hash password
var hashedPassword = BCrypt.Net.BCrypt.HashPassword(request.Password);
// Create user
var user = new User
{
Email = request.Email,
PasswordHash = hashedPassword,
Name = request.Name
};
db.Users.Add(user);
await db.SaveChangesAsync();
return Results.Created($"/api/users/{user.Id}", new UserResponse(user.Id, user.Email, user.Name));
})
.WithName("CreateUser")
.WithOpenApi();
app.Run();
record CreateUserRequest(string Email, string Password, string Name);
record UserResponse(int Id, string Email, string Name);
コントローラーベースの API
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
private readonly AppDbContext _db;
private readonly ILogger<UsersController> _logger;
public UsersController(AppDbContext db, ILogger<UsersController> logger)
{
_db = db;
_logger = logger;
}
[HttpGet]
public async Task<ActionResult<List<UserDto>>> GetUsers()
{
var users = await _db.Users
.AsNoTracking()
.Select(u => new UserDto(u.Id, u.Email, u.Name))
.ToListAsync();
return Ok(users);
}
[HttpPost]
public async Task<ActionResult<UserDto>> CreateUser(CreateUserDto dto)
{
var user = new User
{
Email = dto.Email,
PasswordHash = BCrypt.Net.BCrypt.HashPassword(dto.Password),
Name = dto.Name
};
_db.Users.Add(user);
await _db.SaveChangesAsync();
return Created($"/api/users/{user.Id}", new UserDto(user.Id, user.Email, user.Name));
// Implement the corresponding authorized GET route in the application.
}
}
JWT 認証
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
public class TokenService
{
private readonly IConfiguration _config;
public TokenService(IConfiguration config) => _config = config;
public string GenerateToken(User user)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]!));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Email, user.Email),
new Claim(ClaimTypes.Name, user.Name)
};
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Audience"],
claims: claims,
expires: DateTime.UtcNow.AddHours(1),
signingCredentials: credentials
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
バックグラウンドサービス
public class EmailSenderService : BackgroundService
{
private readonly ILogger<EmailSenderService> _logger;
private readonly IServiceProvider _services;
public EmailSenderService(ILogger<EmailSenderService> logger, IServiceProvider services)
{
_logger = logger;
_services = services;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using var scope = _services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var pendingEmails = await db.PendingEmails
.Where(e => !e.Sent)
.Take(10)
.ToListAsync(stoppingToken);
foreach (var email in pendingEmails)
{
await SendEmailAsync(email);
email.Sent = true;
}
await db.SaveChangesAsync(stoppingToken);
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
}
private async Task SendEmailAsync(PendingEmail email)
{
// Replace with an awaited real provider call; never mark mail sent after a log-only stub.
throw new NotImplementedException("Configure the authorized email provider before enabling this worker");
}
}
遵守するベストプラクティス
- ✅ すべての I/O 操作で Async/await を使用
- ✅ すべてのサービスで依存性注入を使用
- ✅ 設定に appsettings.json を使用
- ✅ ローカル開発に User Secrets を使用
- ✅ Entity Framework のマイグレーション(Add-Migration、Update-Database)
- ✅ グローバル例外処理ミドルウェア
- ✅ 複雑な検証に FluentValidation を使用
- ✅ 構造化ロギングに Serilog を使用
- ✅ ヘルスチェック(AddHealthChecks)
- ✅ API バージョニング
- ✅ Swagger/OpenAPI ドキュメント
- ✅ DTO マッピングに AutoMapper を使用
- ✅ 複雑なドメインでは CQRS と MediatR を使用
制限事項
- モダンな .NET(ASP.NET Core 8 以降)を前提としています。古い .NET Framework プロジェクトでは、異なるパターンが必要になる場合があります。
- クライアント側/フロントエンドの実装は対象外です。
- 明示的に依頼されない限り、クラウドプロバイダー固有のデプロイ詳細(Azure/AWS/GCP)は対象外です。
例は断片です。保護されたルートを公開する前に、モデル/DTO/パッケージを用意し、JWT の発行者、対象者、署名、有効期間の検証を設定してください。登録処理では、パスワードポリシー、一意な正規化済みメールアドレスの処理、レート制限、確立された Identity フローが必要です。認証サービスを追加するだけでは、エンドポイントは保護されません。複数ワーカーによるメール配信では、重複送信を防ぐため、アトミックな処理の確保、結果の永続化、プロバイダー側の冪等性が必要です。
コメント
Markdown 対応