1. GET
Purpose: Retrieve data from a server.
Characteristics:
- Safe & idempotent: It doesn’t modify data on the server.
- Cacheable: Responses can be cached by browsers or CDNs.
-
No body: Parameters go in the URL query string (
/users?id=123).
Example:
GET /users/123
📦 Retrieves the user with ID 123.
2. POST
Purpose: Create a new resource on the server.
Characteristics:
- Not idempotent: Multiple identical requests may create multiple resources.
- Has a body: Data (usually JSON) is sent in the request body.
- Common for: Creating items, submitting forms, authentication, uploads.
Example:
POST /users
Content-Type: application/json
{
"name": "Alice",
"email": "alice@example.com"
}
📦 Creates a new user record.
3. PUT
Purpose: Replace an existing resource entirely.
Characteristics:
- Idempotent: Sending the same request repeatedly results in the same outcome.
- Requires full resource representation — all fields, not just the ones you’re updating.
Example:
PUT /users/123
Content-Type: application/json
{
"name": "Alice Updated",
"email": "alice@newdomain.com"
}
📦 Replaces the entire user record for ID 123.
4. PATCH
Purpose: Partially update a resource.
Characteristics:
- Idempotent (in theory): Usually behaves as such if properly implemented.
- Only includes the fields to change in the request body.
Example:
PATCH /users/123
Content-Type: application/json
{
"email": "alice@newdomain.com"
}
📦 Updates only the email field for user 123.
5. DELETE
Purpose: Remove a resource from the server.
Characteristics:
- Idempotent: Repeated DELETEs have the same effect.
- Usually no body.
Example:
DELETE /users/123
📦 Deletes the user with ID 123.
🧭 Summary Table
| Method | Action | Idempotent | Safe | Request Body | Typical Use |
|---|---|---|---|---|---|
| GET | Retrieve | ✅ | ✅ | ❌ | Fetch data |
| POST | Create | ❌ | ❌ | ✅ | Add new resource |
| PUT | Replace | ✅ | ❌ | ✅ | Full update |
| PATCH | Update | ✅ (mostly) | ❌ | ✅ | Partial update |
| DELETE | Remove | ✅ | ❌ | ❌ (usually) | Delete data |
🧭 Why HTTP verbs matter, why do I care (even if the SQL looks the same)?
When building REST APIs in .NET, it might feel like POST, PUT, or PATCH all do the same thing — after all, they can each trigger the same SQL UPDATE statement.
But the true power of HTTP verbs isn’t about your SQL logic — it’s about how clients, caches, load balancers, and tools interpret your API’s intent.
HTTP verbs define a contract for how requests behave in terms of caching, retries, idempotency, and security. Think of HTTP verbs as contracts between:
- Clients (browsers, mobile apps, other services),
- Servers (your .NET API),
- Intermediaries (load balancers, caches, proxies, frameworks, monitoring tools).
They communicate intent, not implementation.
So while these verbs can all trigger an UPDATE in SQL, their meaning in HTTP defines how the system behaves around that request — caching, retries, idempotency, logging, security, etc.
⚙️ Example Scenario
You have a SQL Server Users table:
Users(Id INT, Name NVARCHAR(50), Email NVARCHAR(100))
You want to:
- Fetch a user
- Create a user
- Replace a user
- Partially update a user’s email
- Delete a user
🚀 RESTful API Design
| Operation | HTTP Verb | Endpoint | Request Body | Behavior |
|---|---|---|---|---|
| Fetch user | GET |
/api/users/123 |
none | Returns JSON for user 123 |
| Create new user | POST |
/api/users |
{ "name": "Alice", "email": "a@b.com" } |
Creates new user (auto-generated ID) |
| Replace entire user | PUT |
/api/users/123 |
{ "name": "Alice", "email": "new@b.com" } |
Replaces user 123’s record entirely |
| Update only email | PATCH |
/api/users/123 |
{ "email": "new@b.com" } |
Updates just the email |
| Delete user | DELETE |
/api/users/123 |
none | Deletes user 123 |
⚡ When the Difference Matters
| Situation | Why Verb Matters |
|---|---|
| Retry Logic |
PUT and DELETE are idempotent — safe to retry after a timeout. POST might create duplicates. |
| Caching |
GET responses can be cached. POST and PATCH cannot. |
| Proxy/CDN Behavior | CDNs can cache GET and invalidate caches after PUT, PATCH, or DELETE. |
| Documentation & SDKs | Tools like Swagger/OpenAPI generate correct docs and client SDKs when verbs are semantically correct. |
| Security | You can enforce different permissions (e.g., GET public, PUT requires Admin). |
| Monitoring | Logs make more sense (DELETE /users → “user deletions”) when verbs match actions. |
🧩 Example: Retrying Requests
If a frontend app calls:
await fetch("/api/users/123", {
method: "PUT",
body: JSON.stringify({ name: "Alice", email: "a@b.com" })
});
and the request times out, the client can safely retry because PUT is idempotent — sending it twice has the same effect.
If it were a POST, two requests might create duplicate users.
✅ Summary
Even though the internal logic (e.g., SQL UPDATE) might be identical:
-
POST→ create new resource -
PUT→ replace resource entirely -
PATCH→ partially update resource -
DELETE→ remove resource -
GET→ retrieve resource
Using the correct HTTP verbs gives your API:
- Predictable behavior
- Correct retry & caching semantics
- Better documentation and tooling
- Compatibility with clients, proxies, and REST conventions
🧠 Tip
You can combine this with:
- Model validation (to verify email format)
- ETags or RowVersion for concurrency control
- Global exception filters for consistent responses
This is where REST verbs and database logic truly complement each other.
Top comments (0)