Skip to content
Open
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
89 changes: 89 additions & 0 deletions .instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# WebAPI Code Review Guidelines

## API Documentation

This is a todo management REST API built with ASP.NET Core 10 using the minimal APIs pattern.

### Current Endpoints

#### GET /todos
- **Name**: GetTodos
- **Description**: Retrieves all todo items
- **Response**: Array of `Todo` objects
- **Status Codes**: 200 OK

#### GET /todos/{id}
- **Name**: GetTodoById
- **Description**: Retrieves a specific todo item by ID
- **Path Parameters**: `id` (int) - The todo item ID
- **Response**: `Todo` object if found, 404 if not found
- **Status Codes**: 200 OK, 404 Not Found

#### POST /todos
- **Name**: CreateTodo
- **Description**: Creates a new todo item
- **Request Body**: Plain string - the todo title
- **Response**: Created `Todo` object with generated ID
- **Status Codes**: 201 Created
- **Location Header**: `/todos/{newId}` pointing to the newly created resource

### Data Model

```csharp
public record Todo(
int Id,
string? Title,
DateOnly? DueBy = null,
bool IsComplete = false
);
```

- **Id**: Unique identifier (auto-generated on creation)
- **Title**: The todo item description
- **DueBy**: Optional due date
- **IsComplete**: Completion status (default: false)

## Code Review Checklist

When reviewing changes to this API, ensure:

### Endpoint Design
- [ ] New endpoints follow the `MapGet/MapPost/MapPut/MapDelete` pattern with the `/todos` group
- [ ] All endpoints have meaningful `WithName()` identifiers
- [ ] HTTP status codes are appropriate (201 for creation, 404 for not found, etc.)
- [ ] POST endpoints use `TypedResults.Created()` and return the created resource

### Data Handling
- [ ] New IDs are generated correctly (current logic: `Max(t => t.Id) + 1`)
- [ ] All todo items are properly serialized/deserialized with `AppJsonSerializerContext`
- [ ] Optional fields are properly nullable (`DateOnly?`, `string?`)

### In-Memory Storage
- [ ] The `sampleTodos` list is a `List<Todo>` (mutable for POST/PUT/DELETE operations)
- [ ] Data operations maintain data integrity
- [ ] Consider future migration to a database when needed

### API Contract
- [ ] All new endpoints are documented with `WithName()`
- [ ] OpenAPI/Swagger documentation is accurate (enable with `app.MapOpenApi()` in Development)
- [ ] Request/response types align with the `Todo` record definition

### Testing Considerations
- [ ] POST endpoint should test ID generation with multiple creates
- [ ] GET endpoints should handle both existing and non-existent IDs
- [ ] Consider testing edge cases (empty lists, max int IDs, etc.)

## Technology Stack

- **.NET**: 10.0
- **Framework**: ASP.NET Core (Minimal APIs)
- **Serialization**: System.Text.Json
- **API Documentation**: OpenAPI (Swagger) support enabled

## Future Enhancement Areas

- Implement DELETE and PUT endpoints for updating and deleting todos
- Add database persistence (Entity Framework Core)
- Add input validation (title length, date validation)
- Implement filtering/pagination for GET /todos
- Add async database operations
25 changes: 17 additions & 8 deletions Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
app.MapOpenApi();
}

Todo[] sampleTodos =
[
new(1, "Walk the dog"),
new(2, "Do the dishes", DateOnly.FromDateTime(DateTime.Now)),
new(3, "Do the laundry", DateOnly.FromDateTime(DateTime.Now.AddDays(1))),
new(4, "Clean the bathroom"),
new(5, "Clean the car", DateOnly.FromDateTime(DateTime.Now.AddDays(2)))
];
var sampleTodos = new List<Todo>
{
new Todo(1, "Walk the dog"),
new Todo(2, "Do the dishes", DateOnly.FromDateTime(DateTime.Now)),
new Todo(3, "Do the laundry", DateOnly.FromDateTime(DateTime.Now.AddDays(1))),
new Todo(4, "Clean the bathroom"),
new Todo(5, "Clean the car", DateOnly.FromDateTime(DateTime.Now.AddDays(2)))
};

var todosApi = app.MapGroup("/todos");
todosApi.MapGet("/", () => sampleTodos)
Expand All @@ -37,6 +37,15 @@
: TypedResults.NotFound())
.WithName("GetTodoById");

todosApi.MapPost("/", (string title) =>
{
var newId = sampleTodos.Max(t => t.Id) + 1;
var newTodo = new Todo(newId, title);
sampleTodos.Add(newTodo);
return TypedResults.Created($"/todos/{newId}", newTodo);
})
.WithName("CreateTodo");

app.Run();

public record Todo(int Id, string? Title, DateOnly? DueBy = null, bool IsComplete = false);
Expand Down
Loading