Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -416,3 +416,7 @@ FodyWeavers.xsd
*.msix
*.msm
*.msp

# LLM-as-a-Judge generated results
tests/calibration-results-*.md
evaluation-results.json
29 changes: 29 additions & 0 deletions skills.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkillEvaluator", "tests\SkillEvaluator\SkillEvaluator.csproj", "{AF693849-67F7-2D6B-2515-1438EB8562A8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AF693849-67F7-2D6B-2515-1438EB8562A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF693849-67F7-2D6B-2515-1438EB8562A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF693849-67F7-2D6B-2515-1438EB8562A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF693849-67F7-2D6B-2515-1438EB8562A8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{AF693849-67F7-2D6B-2515-1438EB8562A8} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {81F1EB1F-56DC-49A1-93CD-17AE5828FE61}
EndGlobalSection
EndGlobal
145 changes: 145 additions & 0 deletions skills/analyzing-build-errors/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
---
name: analyzing-build-errors
description: Triage and resolve .NET build failures including compilation errors, NuGet restore issues, SDK version mismatches, and MSBuild target errors. Use when dotnet build fails, NuGet restore produces errors, or the user encounters red squiggles and build diagnostics.
---

# Analyzing Build Errors

## When to Use

- `dotnet build` fails with compilation errors
- `dotnet restore` fails with NuGet resolution errors
- MSBuild produces warnings or errors about targets, props, or SDK versions
- The user reports red squiggles in their IDE that block compilation

## When Not to Use

- The issue is a runtime exception (not a build error)
- The user wants to improve code quality without fixing build breaks
- The errors are from a non-.NET build system

## Inputs

| Input | Required | Description |
|-------|----------|-------------|
| Project or solution path | Yes | The `.sln` or `.csproj` that fails to build |
| Error output | No | The raw error text; if not provided, run `dotnet build` to capture it |

## Workflow

### Step 1: Reproduce the failure

```bash
dotnet build <project-or-solution> 2>&1
```

Capture the full output. Errors follow the format:

```
<file>(<line>,<col>): error <CODE>: <message>
```

### Step 2: Categorize the error

| Error Code Pattern | Category | Go To |
|---|---|---|
| `CS####` | C# compiler error | [Compiler errors](#compiler-errors) |
| `NU####` | NuGet error | [NuGet errors](#nuget-errors) |
| `MSB####` | MSBuild error | [MSBuild errors](#msbuild-errors) |
| `NETSDK####` | .NET SDK error | [SDK errors](#sdk-errors) |

### Compiler errors

The most common `CS` errors and their fixes:

| Error | Meaning | Fix |
|---|---|---|
| `CS0246` | Type or namespace not found | Add missing `using` directive or NuGet package reference |
| `CS1061` | Member not found on type | Check for typos, missing interface implementation, or wrong type |
| `CS0103` | Name does not exist in scope | Declare the variable, or fix the scope |
| `CS8600`-`CS8605` | Nullable reference warnings-as-errors | Add null checks, use `!`, or adjust nullable annotations |
| `CS0619` | Obsolete API used as error | Replace with the recommended API from the error message |
| `CS0029` | Cannot implicitly convert type | Add explicit cast or fix the type mismatch |

For other `CS` errors, use the error code to look up documentation:

```
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs<NUMBER>
```

### NuGet errors

| Error | Meaning | Fix |
|---|---|---|
| `NU1100` | Unable to resolve package | Check package name spelling, NuGet source configuration |
| `NU1102` | Package version not found | Verify version exists; try `dotnet nuget list source` |
| `NU1202` | Package not compatible with target framework | Find a compatible version or an alternative package |
| `NU1605` | Package downgrade detected | Align versions across projects or use central package management |
| `NU1903` | Known vulnerability in package | Update to patched version listed in the warning |

Restore diagnostics:

```bash
dotnet restore --verbosity detailed
```

### MSBuild errors

| Error | Meaning | Fix |
|---|---|---|
| `MSB3644` | Reference assemblies not found | Install the targeting pack for the framework version |
| `MSB4019` | Imported project not found | Verify SDK installation, check `global.json` |
| `MSB3270` | Processor architecture mismatch | Align `PlatformTarget` in project files |

### SDK errors

| Error | Meaning | Fix |
|---|---|---|
| `NETSDK1045` | SDK version too old | Update SDK or adjust `global.json` |
| `NETSDK1004` | Assets file not found | Run `dotnet restore` first |
| `NETSDK1005` | Assets file has wrong target | Delete `obj/` folder and restore again |
| `NETSDK1141` | SDK version in `global.json` not found | Install matching SDK or remove the `global.json` constraint |

### Step 3: Apply the fix

Make the specific code or project file change. Then rebuild:

```bash
dotnet build <project-or-solution>
```

### Step 4: Verify the fix

- [ ] Build succeeds with zero errors
- [ ] No new warnings introduced (or warnings are acknowledged)
- [ ] `dotnet test` still passes (if tests exist)

## Triage Shortcut: Clean Rebuild

When the error seems stale or inconsistent with the code:

```bash
dotnet clean
dotnet nuget locals all --clear
dotnet restore
dotnet build
```

This resolves most phantom build errors caused by stale caches.

## Validation

- [ ] `dotnet build` produces zero errors
- [ ] Root cause of each error is identified
- [ ] Fix is minimal and targeted (no unrelated changes)
- [ ] No new warnings elevated to errors

## Common Pitfalls

| Pitfall | Solution |
|---------|----------|
| Fixing symptoms instead of root cause | Read the full error message; the root error is often the last one |
| Build order issues in solutions | Check `ProjectReference` dependencies; build the dependency first |
| `global.json` pinning a missing SDK | Remove or update the `global.json` file |
| NuGet source authentication failures | Run `dotnet nuget list source` and verify credentials |
| Incremental build inconsistencies | Use `dotnet clean` followed by full rebuild |
182 changes: 182 additions & 0 deletions skills/creating-minimal-apis/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
---
name: creating-minimal-apis
description: Build ASP.NET Core Minimal API endpoints for HTTP services, including routing, validation, dependency injection, and OpenAPI documentation. Use when creating new REST API endpoints, lightweight HTTP services, or microservice backends in .NET.
---

# Creating Minimal APIs

## When to Use

- Building a new HTTP API or microservice from scratch
- Adding lightweight endpoints to an existing ASP.NET Core app
- Prototyping an API quickly without controllers
- The user asks to create REST endpoints in .NET

## When Not to Use

- The project uses MVC controllers and the user wants to stay with that pattern
- The user needs SignalR, gRPC, or GraphQL (not HTTP REST)
- The project targets .NET 5 or earlier (Minimal APIs require .NET 6+)

## Inputs

| Input | Required | Description |
|-------|----------|-------------|
| API requirements | Yes | Endpoints, resources, and operations to expose |
| Existing project | No | Path to an existing ASP.NET Core project; created if absent |

## Workflow

### Step 1: Create or verify the project

If no project exists:

```bash
dotnet new web -o src/MyApi
dotnet sln add src/MyApi
```

Verify the project targets .NET 8 or later for the best Minimal API experience.

### Step 2: Define the data model

```csharp
public record Todo(int Id, string Title, bool IsComplete);
```

Use records for DTOs. They provide immutability and value equality by default.

### Step 3: Create endpoints

Structure endpoints in `Program.cs` or use extension methods for organization:

```csharp
var builder = WebApplication.CreateBuilder(args);

// Register services
builder.Services.AddSingleton<ITodoService, TodoService>();

var app = builder.Build();

// Map endpoints
var todos = app.MapGroup("/api/todos");
todos.MapGet("/", (ITodoService service) => service.GetAll());
todos.MapGet("/{id:int}", (int id, ITodoService service) =>
service.GetById(id) is { } todo
? Results.Ok(todo)
: Results.NotFound());
todos.MapPost("/", (Todo todo, ITodoService service) =>
{
var created = service.Create(todo);
return Results.Created($"/api/todos/{created.Id}", created);
});
todos.MapPut("/{id:int}", (int id, Todo todo, ITodoService service) =>
service.Update(id, todo) ? Results.NoContent() : Results.NotFound());
todos.MapDelete("/{id:int}", (int id, ITodoService service) =>
service.Delete(id) ? Results.NoContent() : Results.NotFound());

app.Run();
```

### Step 4: Add validation

Install the validation package:

```bash
dotnet add package FluentValidation.DependencyInjectionExtensions
```

Create a validator:

```csharp
using FluentValidation;

public class TodoValidator : AbstractValidator<Todo>
{
public TodoValidator()
{
RuleFor(t => t.Title).NotEmpty().MaximumLength(200);
}
}
```

Apply validation in the endpoint using an endpoint filter:

```csharp
todos.MapPost("/", (Todo todo, ITodoService service) =>
{
var created = service.Create(todo);
return Results.Created($"/api/todos/{created.Id}", created);
}).AddEndpointFilter<ValidationFilter<Todo>>();
```

### Step 5: Add OpenAPI documentation

```csharp
builder.Services.AddOpenApi();

// After building the app:
app.MapOpenApi();
```

Run the app and verify the OpenAPI document is available at `/openapi/v1.json`.

### Step 6: Organize for larger APIs

For APIs with many endpoints, extract into extension methods:

```csharp
// TodoEndpoints.cs
public static class TodoEndpoints
{
public static RouteGroupBuilder MapTodoEndpoints(this WebApplication app)
{
var group = app.MapGroup("/api/todos");
group.MapGet("/", GetAll);
group.MapGet("/{id:int}", GetById);
group.MapPost("/", Create);
return group;
}

private static IResult GetAll(ITodoService service) => Results.Ok(service.GetAll());
private static IResult GetById(int id, ITodoService service) =>
service.GetById(id) is { } todo ? Results.Ok(todo) : Results.NotFound();
private static IResult Create(Todo todo, ITodoService service) =>
Results.Created($"/api/todos/{service.Create(todo).Id}", todo);
}

// Program.cs
app.MapTodoEndpoints();
```

### Step 7: Run and test

```bash
dotnet run --project src/MyApi
```

Verify with curl or any HTTP client:

```bash
curl http://localhost:5000/api/todos
curl -X POST http://localhost:5000/api/todos -H "Content-Type: application/json" -d '{"id":0,"title":"Buy milk","isComplete":false}'
```

## Validation

- [ ] `dotnet build` compiles without errors
- [ ] `dotnet run` starts the server successfully
- [ ] GET endpoints return expected data
- [ ] POST endpoint creates resources and returns 201
- [ ] Invalid input returns 400 (if validation is added)
- [ ] OpenAPI document is accessible at `/openapi/v1.json`

## Common Pitfalls

| Pitfall | Solution |
|---------|----------|
| Route conflicts between endpoints | Use `MapGroup` with unique prefixes |
| Missing `[FromBody]` / `[FromQuery]` | Minimal APIs infer binding; use attributes only when ambiguous |
| CORS errors from browser clients | Add `builder.Services.AddCors()` and `app.UseCors()` |
| Port conflicts | Set port in `launchSettings.json` or `--urls` flag |
| Forgetting to register services | All dependencies must be registered in `builder.Services` |
Loading