From qe-framework
Builds C# applications with .NET 8+, ASP.NET Core APIs, Blazor, and Entity Framework Core. Implements CQRS, JWT auth, AOT compilation, and async patterns.
How this skill is triggered — by the user, by Claude, or both
Slash command
/qe-framework:Qcsharp-developerThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Senior C# developer with mastery of .NET 8+ and Microsoft ecosystem. Specializes in high-performance web APIs, cloud-native solutions, and modern C# language features.
Senior C# developer with mastery of .NET 8+ and Microsoft ecosystem. Specializes in high-performance web APIs, cloud-native solutions, and modern C# language features.
EF Core checkpoint (after step 3): Run
dotnet ef migrations add <Name>and review the generated migration file before applying. Confirm no unintended table/column drops. Roll back withdotnet ef migrations removeif needed.
Load detailed guidance based on context:
| Topic | Reference | Load When |
|---|---|---|
| Modern C# | references/modern-csharp.md | Records, pattern matching, nullable types |
| ASP.NET Core | references/aspnet-core.md | Minimal APIs, middleware, DI, routing |
| Entity Framework | references/entity-framework.md | EF Core, migrations, query optimization |
| Blazor | references/blazor.md | Components, state management, interop |
| Performance | references/performance.md | Span, async, memory optimization, AOT |
CancellationToken:
// Correct
app.MapGet("/items/{id}", async (int id, IItemService svc, CancellationToken ct) =>
await svc.GetByIdAsync(id, ct) is { } item ? Results.Ok(item) : Results.NotFound());
public readonly record struct Result<T>(T? Value, string? Error, bool IsSuccess)
{
public static Result<T> Ok(T value) => new(value, null, true);
public static Result<T> Fail(string error) => new(default, error, false);
}
IOptions<T>.Result, .Wait()) in async code:
// Wrong — blocks thread and risks deadlock
var data = service.GetDataAsync().Result;
// Correct
var data = await service.GetDataAsync(ct);
When implementing .NET features, provide:
Basic: Class with DI + XML Documentation
/// <summary>Manages user authentication and token generation.</summary>
public class AuthService(ITokenGenerator tokenGen, ILogger<AuthService> logger)
{
/// <summary>Authenticates user credentials and returns JWT token.</summary>
/// <param name="username">User's login name</param>
/// <param name="password">User's plaintext password</param>
/// <returns>JWT token if successful; empty string if failed</returns>
public async Task<string> LoginAsync(string username, string password, CancellationToken ct)
{
logger.LogInformation("Login attempt for {Username}", username);
return await tokenGen.GenerateAsync(username, ct);
}
}
Error Handling: Result Pattern
public class OrderService(IRepository<Order> repo)
{
public async Task<Result<OrderDto>> CreateOrderAsync(CreateOrderRequest req, CancellationToken ct)
{
if (req.Items.Count == 0)
return Result<OrderDto>.Fail("Order must contain at least one item");
var order = new Order { Items = req.Items };
await repo.AddAsync(order, ct);
return Result<OrderDto>.Ok(new OrderDto { Id = order.Id });
}
}
Advanced: Async/Await + IAsyncDisposable
/// <remarks>Implements async disposal for proper resource cleanup.</remarks>
public class DataProcessor : IAsyncDisposable
{
private readonly HttpClient _client;
public async ValueTask<T> ProcessAsync<T>(string url, CancellationToken ct) where T : class
{
using var response = await _client.GetAsync(url, ct);
return await response.Content.ReadAsAsync<T>(cancellationToken: ct);
}
async ValueTask IAsyncDisposable.DisposeAsync()
{
_client?.Dispose();
await Task.CompletedTask;
}
}
Method XML Documentation
/// <summary>Fetches a user by unique identifier.</summary>
/// <param name="userId">The user's primary key</param>
/// <param name="ct">Cancellation token</param>
/// <returns>User DTO or null if not found</returns>
/// <exception cref="ArgumentException">Thrown when userId is invalid</exception>
public async Task<UserDto?> GetUserAsync(int userId, CancellationToken ct)
Class XML Documentation
/// <summary>Provides email delivery and SMTP configuration.</summary>
/// <remarks>Uses SMTP relay from appsettings. Retries transient failures up to 3 times.</remarks>
/// <example>var mailer = new EmailService(config); await mailer.SendAsync(to, subject, body, ct);</example>
public class EmailService { }
File-level namespace header
/// <summary>User domain models and value objects for authentication flow.</summary>
namespace MyApp.Domain.Users;
dotnet format {project} + dotnet build -warnaserror.editorconfig, .globalconfig[*.cs]
dotnet_diagnostic.CS8600.severity = error
dotnet_diagnostic.SA1600.severity = error
| Anti-pattern | Wrong | Correct |
|---|---|---|
| Service Locator | var svc = container.Resolve<IService>() | Constructor DI: public Ctrl(IService svc) |
| async void | async void OnClick() { await Task.Delay(1000); } | async Task OnClick() { await Task.Delay(1000); } |
| Catching all | catch (Exception ex) { } | catch (DbUpdateException ex) { log error; } |
| String SQL | $"SELECT * FROM Users WHERE Id={id}" | await ctx.Users.FromSqlInterpolated($"... WHERE Id={id}") |
| Not disposing | var conn = new SqlConnection(); conn.Open(); | using (var conn = new SqlConnection()) { ... } |
// Program.cs (file-scoped, .NET 8 minimal API)
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IProductService, ProductService>();
var app = builder.Build();
app.MapGet("/products/{id:int}", async (
int id,
IProductService service,
CancellationToken ct) =>
{
var result = await service.GetByIdAsync(id, ct);
return result.IsSuccess ? Results.Ok(result.Value) : Results.NotFound(result.Error);
})
.WithName("GetProduct")
.Produces<ProductDto>()
.ProducesProblem(404);
app.Run();
C# 12, .NET 8, ASP.NET Core, Minimal APIs, Blazor (Server/WASM), Entity Framework Core, MediatR, xUnit, Moq, Benchmark.NET, SignalR, gRPC, Azure SDK, Polly, FluentValidation, Serilog
npx claudepluginhub inho-team/qe-framework --plugin qe-frameworkCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.