The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →To create, read, update, and delete data in a C# Web API, first define a consistent HTTP contract, then make each endpoint’s behavior explicit: creation identifies the new resource, reads distinguish missing data, updates state whether they replace or partially change it, and validation errors follow a predictable format.
This walkthrough uses ASP.NET Core Minimal APIs for its examples. Microsoft recommends Minimal APIs for new projects, while continuing to support controller-based APIs; an existing codebase’s conventions and the structure your team needs are good reasons to choose controllers instead. The examples are illustrative patterns, not tested code. Microsoft’s ASP.NET Core 10.0 API overview describes the Minimal API recommendation, and its ASP.NET Core 10.0 Web API guidance covers controller-based APIs.
As an Amazon Associate I earn from qualifying purchases.
Start with a clear resource and route contract
Use one resource name consistently for the collection and individual items. In this example, the collection is /api/todo-items and an individual item is /api/todo-items/{id}. The HTTP method and route together should make the intended operation clear.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →| Operation | Request | Purpose |
|---|---|---|
| Create | POST /api/todo-items |
Create a new item and identify its resource URI. |
| Read collection | GET /api/todo-items |
Return the collection. |
| Read item | GET /api/todo-items/{id} |
Return the matching item or a not-found response. |
| Replace item | PUT /api/todo-items/{id} |
Replace an item using a complete representation. |
| Delete item | DELETE /api/todo-items/{id} |
Apply the API’s documented deletion outcome. |
Keep the contract consistent across handlers and documentation. Avoid routes or response bodies that make clients guess whether an operation succeeded or which resource was affected.
#1 Best Overall
Create: identify what was created
A fragile create endpoint returns a generic success with no way for the client to locate the new item. A more useful contract responds with 201 Created and a Location header containing the URI of the created resource. A client can use that URI to retrieve the resource or refer to it in a later operation.
Microsoft’s controller-based tutorial demonstrates this with CreatedAtAction, which produces a creation response and a Location header for the new resource. See the ASP.NET Core 10.0 controller tutorial. In a Minimal API, choose a response helper or explicit result that expresses the same contract; the key is that the response identifies the created resource.
Read: distinguish an empty collection from a missing item
Read the collection
GET /api/todo-items returns the collection. An empty collection is a valid result when there are currently no items; it is not the same as failing to find a particular item.
Rank #2
Read one item
GET /api/todo-items/{id} returns the item when it exists and a not-found outcome when it does not. Returning a fabricated empty object or hiding absence inside a generic success makes client behavior ambiguous. Microsoft’s Minimal API tutorial illustrates JSON responses for found items and 404 Not Found for missing ones. Its examples are from a versioned ASP.NET Core 6.0 page, so treat them as examples rather than a current API template. Review the Minimal API tutorial examples.
Update: make PUT replacement semantics explicit
Do not silently treat a sparse request body as a complete update. In this contract, PUT /api/todo-items/{id} accepts the full client-writable representation of the item. The cited Minimal API tutorial describes PUT as requiring the client to send the entire updated entity, and shows a successful response with 204 No Content when there is no response body.
If clients need to change only selected fields, expose a separately defined partial-update operation, such as PATCH, and document which fields it accepts and what happens when fields are omitted. Do not label partial-update behavior as full PUT. The exact response for an update should match the API’s contract; the cited tutorial’s 204 is an example, not a universal response requirement.
Delete: document the outcome your API promises
Make clear whether a successful DELETE /api/todo-items/{id} returns an empty response, a representation, or another documented result. Choose a response that matches that contract, and define how the endpoint behaves when the requested item does not exist. Do not imply that one success status is mandatory for every API; clients need a consistent, documented outcome.
Free tools Windows power users keep installed
One-click scans. No signup required.
Validate requests and keep errors machine-readable
Validate incoming values at the API boundary before accepting them for persistence. Specify which fields are required and which values are allowed, then return errors in a consistent format that clients can inspect instead of parsing ad hoc text.
For controller-based APIs, applying [ApiController] can cause invalid model state to produce an automatic HTTP 400 response. ASP.NET Core documents ValidationProblemDetails for validation errors and ProblemDetails for error status codes. These conventions help clients distinguish invalid input from other failures. Microsoft’s ASP.NET Core 10.0 Web API guidance covers these controller conventions.
Rank #4
Use input and output models instead of exposing a broad entity
Binding an untrusted request body directly to a persistence entity is fragile when that entity contains fields the client should not control or see. A client could submit server-managed values along with the fields intended for editing. Define an input model containing only writable fields, and an output model containing only the data the API should expose.
Microsoft’s controller tutorial identifies preventing over-posting, hiding properties, reducing payload size, and flattening nested object graphs as reasons to use a DTO or view model. See its DTO and over-posting guidance. Map between API models and persistence entities deliberately so that writable fields remain an explicit part of the contract.
Verify the contract with real requests
Use a request tool to check the routes and responses your API documents. Microsoft’s controller tutorial lists .http files, http-repl, curl, and Fiddler among request-testing options. No requests are executed here; the examples below show what a client might send and what to inspect.
Best Value
Create an item
POST /api/todo-items HTTP/1.1
Content-Type: application/json
{
"title": "Review the API contract",
"isComplete": false
}
Check that the successful response communicates creation and includes a Location header pointing to the new item. The exact response body depends on the API’s contract.
Read an item
GET /api/todo-items/42 HTTP/1.1
Check that an existing item is returned as JSON and a nonexistent item produces the documented not-found response.
Replace an item
PUT /api/todo-items/42 HTTP/1.1
Content-Type: application/json
{
"title": "Review the API contract",
"isComplete": true
}
Supply the full client-writable representation when using the replacement contract. Also check that invalid input produces the API’s documented validation error shape.
For broader implementation choices, Microsoft’s ASP.NET Core 10.0 best-practices guidance is a useful companion. The framework documentation supports both Minimal APIs and controllers; it does not establish a quantitative performance comparison for the particular application you are building.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




