← Back to Articles         
Angular HttpClient: GET, POST, PUT, DELETE

Angular HttpClient: GET, POST, PUT, DELETE

Published on 01 Oct 2026     11 min read Angular
HTTP & Web API Integration

Angular HttpClient: GET, POST, PUT, DELETE

Angular uses HttpClient to communicate with an ASP.NET Core Web API.

The four most common operations are:

Operation Angular Purpose ASP.NET Core
GET http.get() Read [HttpGet]
POST http.post() Create [HttpPost]
PUT http.put() Update [HttpPut]
DELETE http.delete() Delete [HttpDelete]

These are commonly called CRUD operations:

Create → POST
Read   → GET
Update → PUT
Delete → DELETE

Full Simple Sample Program

Suppose our ASP.NET Core Web API exposes:

GET     /api/products
GET     /api/products/1
POST    /api/products
PUT     /api/products/1
DELETE  /api/products/1

1. app.config.ts

First configure HttpClient:

import { ApplicationConfig } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient()
  ]
};

2. product.ts

export interface Product {
  id: number;
  name: string;
  price: number;
}

3. product.service.ts

This contains all four HTTP operations.

import { inject, Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

import { Product } from './product';

@Injectable({
  providedIn: 'root'
})
export class ProductService {

  private http = inject(HttpClient);

  private apiUrl =
    'https://localhost:7001/api/products';


  // GET - Get all products
  getProducts(): Observable<Product[]> {

    return this.http.get<Product[]>(
      this.apiUrl
    );

  }


  // GET - Get one product
  getProduct(id: number): Observable<Product> {

    return this.http.get<Product>(
      `${this.apiUrl}/${id}`
    );

  }


  // POST - Create product
  addProduct(product: Product): Observable<Product> {

    return this.http.post<Product>(
      this.apiUrl,
      product
    );

  }


  // PUT - Update product
  updateProduct(
    id: number,
    product: Product
  ): Observable<void> {

    return this.http.put<void>(
      `${this.apiUrl}/${id}`,
      product
    );

  }


  // DELETE - Delete product
  deleteProduct(id: number): Observable<void> {

    return this.http.delete<void>(
      `${this.apiUrl}/${id}`
    );

  }

}

This service is the main code to remember.


1. How Do You Perform a GET Request?

What is GET?

GET is used to retrieve/read data from the server.

For example:

GET /api/products

means:

Give me all products.


Angular Syntax

this.http.get<T>(url);

Here T represents the expected response type.

For example:

this.http.get<Product[]>(url);

means we expect an array of products.


Get All Products

getProducts(): Observable<Product[]> {

  return this.http.get<Product[]>(
    this.apiUrl
  );

}

Angular sends:

GET https://localhost:7001/api/products

ASP.NET Core might have:

[HttpGet]
public ActionResult<IEnumerable<Product>> GetProducts()
{
    return Ok(products);
}

The API returns:

[
  {
    "id": 1,
    "name": "Laptop",
    "price": 75000
  },
  {
    "id": 2,
    "name": "Mouse",
    "price": 1200
  }
]

The flow is:

Angular
   ↓
http.get<Product[]>()
   ↓
GET /api/products
   ↓
ASP.NET Core [HttpGet]
   ↓
JSON response
   ↓
Observable<Product[]>

GET a Single Product

If we want product 10:

getProduct(id: number): Observable<Product> {

  return this.http.get<Product>(
    `${this.apiUrl}/${id}`
  );

}

Calling:

this.productService.getProduct(10);

produces:

GET https://localhost:7001/api/products/10

ASP.NET Core:

[HttpGet("{id}")]
public ActionResult<Product> GetProduct(int id)
{
    // Find product

    return Ok(product);
}

2. How Do You Perform a POST Request?

What is POST?

POST is normally used to create a new resource.

For example:

POST /api/products

means:

Create a new product.


Angular Syntax

this.http.post<T>(
  url,
  body
);

There are two important parameters:

url
 ↓
Where should the request go?

body
 ↓
What data should be sent?

Example

addProduct(product: Product): Observable<Product> {

  return this.http.post<Product>(
    this.apiUrl,
    product
  );

}

Suppose:

const product: Product = {
  id: 0,
  name: 'Monitor',
  price: 15000
};

and we call:

this.productService.addProduct(product);

Angular sends conceptually:

POST https://localhost:7001/api/products
Content-Type: application/json

with a request body like:

{
  "id": 0,
  "name": "Monitor",
  "price": 15000
}

ASP.NET Core:

[HttpPost]
public ActionResult<Product> AddProduct(Product product)
{
    // Save product

    return Ok(product);
}

Flow:

Angular Product object
        ↓
http.post()
        ↓
POST /api/products
        ↓
JSON request body
        ↓
ASP.NET Core [HttpPost]
        ↓
Create product
        ↓
JSON response

3. How Do You Perform a PUT Request?

What is PUT?

PUT is commonly used to update an existing resource.

For example:

PUT /api/products/10

means:

Update product 10.


Angular Syntax

this.http.put<T>(
  url,
  body
);

Like POST, PUT usually sends a request body.


Example

updateProduct(
  id: number,
  product: Product
): Observable<void> {

  return this.http.put<void>(
    `${this.apiUrl}/${id}`,
    product
  );

}

Suppose:

const product: Product = {
  id: 10,
  name: 'Gaming Monitor',
  price: 25000
};

Call:

this.productService.updateProduct(
  10,
  product
);

Angular sends:

PUT https://localhost:7001/api/products/10
Content-Type: application/json

Body:

{
  "id": 10,
  "name": "Gaming Monitor",
  "price": 25000
}

ASP.NET Core:

[HttpPut("{id}")]
public IActionResult UpdateProduct(
    int id,
    Product product)
{
    // Update product

    return NoContent();
}

Flow:

Updated Product object
        ↓
http.put()
        ↓
PUT /api/products/10
        ↓
JSON request body
        ↓
ASP.NET Core [HttpPut]
        ↓
Update product
        ↓
204 No Content

4. How Do You Perform a DELETE Request?

What is DELETE?

DELETE is used to delete a resource.

For example:

DELETE /api/products/10

means:

Delete product 10.


Angular Syntax

this.http.delete<T>(url);

Unlike POST and PUT, a typical REST DELETE request identifies the resource through the URL and does not require a request body.


Example

deleteProduct(id: number): Observable<void> {

  return this.http.delete<void>(
    `${this.apiUrl}/${id}`
  );

}

Calling:

this.productService.deleteProduct(10);

sends:

DELETE https://localhost:7001/api/products/10

ASP.NET Core:

[HttpDelete("{id}")]
public IActionResult DeleteProduct(int id)
{
    // Delete product

    return NoContent();
}

Flow:

Product ID
    ↓
deleteProduct(10)
    ↓
http.delete()
    ↓
DELETE /api/products/10
    ↓
ASP.NET Core [HttpDelete]
    ↓
Delete product
    ↓
204 No Content

Using These Methods From a Component

The service returns Observables, so the component subscribes to them.

GET

loadProducts(): void {

  this.productService
    .getProducts()
    .subscribe({
      next: (data) => {
        this.products = data;
      },
      error: (error) => {
        console.error(error);
      }
    });

}

POST

addProduct(): void {

  const product: Product = {
    id: 0,
    name: 'Monitor',
    price: 15000
  };

  this.productService
    .addProduct(product)
    .subscribe({
      next: (result) => {
        console.log('Created:', result);
      },
      error: (error) => {
        console.error(error);
      }
    });

}

PUT

updateProduct(): void {

  const product: Product = {
    id: 10,
    name: 'Gaming Monitor',
    price: 25000
  };

  this.productService
    .updateProduct(10, product)
    .subscribe({
      next: () => {
        console.log('Product updated');
      },
      error: (error) => {
        console.error(error);
      }
    });

}

DELETE

deleteProduct(id: number): void {

  this.productService
    .deleteProduct(id)
    .subscribe({
      next: () => {
        console.log('Product deleted');
      },
      error: (error) => {
        console.error(error);
      }
    });

}

Complete CRUD Flow

For an Angular + ASP.NET Core application:

                 Angular
                    │
              ProductService
                    │
                 HttpClient
                    │
      ┌─────────────┼──────────────┐
      │             │              │
     GET           POST           PUT          DELETE
      │             │              │              │
      ↓             ↓              ↓              ↓
    Read          Create         Update          Delete
      │             │              │              │
      └─────────────┼──────────────┼──────────────┘
                    ↓
             ASP.NET Core API
                    ↓
                  EF Core
                    ↓
                SQL Server

Important Syntax to Remember

For interviews, these four lines are the most important:

// GET
this.http.get<Product[]>(url);

// POST
this.http.post<Product>(url, product);

// PUT
this.http.put<void>(url, product);

// DELETE
this.http.delete<void>(url);

Or even more simply:

GET
http.get(url)

POST
http.post(url, body)

PUT
http.put(url, body)

DELETE
http.delete(url)

Notice the pattern:

GET     → URL

POST    → URL + BODY

PUT     → URL + BODY

DELETE  → URL

Why Observable<void> for PUT and DELETE?

You may have noticed:

Observable<void>

for:

updateProduct()
deleteProduct()

That's because an ASP.NET Core API often returns:

return NoContent();

which produces:

HTTP 204 No Content

There is no response body.

Therefore:

Observable<void>

is appropriate.

If your API returns the updated product instead, you could use:

Observable<Product>

For example:

return this.http.put<Product>(
  `${this.apiUrl}/${id}`,
  product
);

The TypeScript response type should match the API's response contract.


Key Points

  • Angular uses HttpClient for HTTP requests.
  • GET retrieves data.
  • POST normally creates data.
  • PUT normally updates/replaces an existing resource.
  • DELETE deletes a resource.
  • POST and PUT normally send a request body.
  • GET and typical DELETE requests generally identify data through the URL.
  • Angular HttpClient methods return RxJS Observables.
  • The generic type specifies the expected response:
get<Product[]>()
post<Product>()
put<void>()
delete<void>()
  • A clean Angular structure is:
Component
    ↓
Service
    ↓
HttpClient
    ↓
ASP.NET Core Web API

Interview Questions and Answers

1. How do you perform a GET request in Angular?

Use HttpClient.get():

return this.http.get<Product[]>(
  '/api/products'
);

It is used to retrieve data from the API.


2. How do you perform a POST request?

Use HttpClient.post():

return this.http.post<Product>(
  '/api/products',
  product
);

POST is commonly used to create a new resource.


3. How do you perform a PUT request?

Use HttpClient.put():

return this.http.put<void>(
  `/api/products/${id}`,
  product
);

PUT is commonly used to update an existing resource.


4. How do you perform a DELETE request?

Use HttpClient.delete():

return this.http.delete<void>(
  `/api/products/${id}`
);

It sends an HTTP DELETE request to remove the specified resource.


5. What do Angular HttpClient methods return?

They return RxJS Observables.

For example:

Observable<Product[]>

6. What is the difference between POST and PUT?

POST is commonly used to create a new resource:

POST /api/products

PUT is commonly used to update/replace a known resource:

PUT /api/products/10

7. What does <Product[]> mean here?

this.http.get<Product[]>(url);

It tells TypeScript that the application expects the response to have the shape of an array of Product objects.


Short Interview Answer

Angular performs CRUD operations using HttpClient: get() retrieves data, post() creates data, put() updates data, and delete() removes data. These methods send HTTP requests to the ASP.NET Core Web API and return RxJS Observables containing the response.

 

Below is a complete Angular standalone example showing HttpClient with GET, POST, PUT, and DELETE. It assumes an API exists at https://localhost:7001/api/products.

Project files

src/
├── app/
│   ├── app.ts
│   ├── app.html
│   ├── app.css
│   ├── product.ts
│   └── product.service.ts
├── app.config.ts
└── main.ts

1. product.ts

export interface Product {
  id: number;
  name: string;
  price: number;
}

2. product.service.ts

import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Product } from './product';

@Injectable({
  providedIn: 'root'
})
export class ProductService {

  private http = inject(HttpClient);

  private apiUrl = 'https://localhost:7001/api/products';

  // GET - Get all products
  getProducts(): Observable<Product[]> {
    return this.http.get<Product[]>(this.apiUrl);
  }

  // GET - Get product by ID
  getProduct(id: number): Observable<Product> {
    return this.http.get<Product>(`${this.apiUrl}/${id}`);
  }

  // POST - Create product
  createProduct(product: Product): Observable<Product> {
    return this.http.post<Product>(
      this.apiUrl,
      product
    );
  }

  // PUT - Update product
  updateProduct(id: number, product: Product): Observable<void> {
    return this.http.put<void>(
      `${this.apiUrl}/${id}`,
      product
    );
  }

  // DELETE - Delete product
  deleteProduct(id: number): Observable<void> {
    return this.http.delete<void>(
      `${this.apiUrl}/${id}`
    );
  }
}

3. app.config.ts

In a standalone Angular application, configure HttpClient using provideHttpClient().

import { ApplicationConfig } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient()
  ]
};

4. app.ts

import { Component, OnInit, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ProductService } from './product.service';
import { Product } from './product';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './app.html',
  styleUrl: './app.css'
})
export class App implements OnInit {

  private productService = inject(ProductService);

  products: Product[] = [];

  ngOnInit(): void {
    this.loadProducts();
  }

  // GET
  loadProducts(): void {

    this.productService.getProducts().subscribe({
      next: (data) => {
        this.products = data;
      },
      error: (error) => {
        console.error('GET Error:', error);
      }
    });
  }

  // POST
  addProduct(): void {

    const product: Product = {
      id: 0,
      name: 'Laptop',
      price: 75000
    };

    this.productService.createProduct(product).subscribe({
      next: (createdProduct) => {
        console.log('Product created:', createdProduct);

        this.loadProducts();
      },
      error: (error) => {
        console.error('POST Error:', error);
      }
    });
  }

  // PUT
  updateProduct(id: number): void {

    const product: Product = {
      id: id,
      name: 'Gaming Laptop',
      price: 95000
    };

    this.productService.updateProduct(id, product).subscribe({
      next: () => {
        console.log('Product updated');

        this.loadProducts();
      },
      error: (error) => {
        console.error('PUT Error:', error);
      }
    });
  }

  // DELETE
  deleteProduct(id: number): void {

    this.productService.deleteProduct(id).subscribe({
      next: () => {
        console.log('Product deleted');

        this.loadProducts();
      },
      error: (error) => {
        console.error('DELETE Error:', error);
      }
    });
  }
}

5. app.html

<h1>Angular HttpClient CRUD</h1>

<button (click)="addProduct()">
  Add Product
</button>

<hr>

<table border="1">
  <thead>
    <tr>
      <th>Id</th>
      <th>Name</th>
      <th>Price</th>
      <th>Actions</th>
    </tr>
  </thead>

  <tbody>
    @for (product of products; track product.id) {

      <tr>
        <td>{{ product.id }}</td>
        <td>{{ product.name }}</td>
        <td>{{ product.price }}</td>

        <td>
          <button (click)="updateProduct(product.id)">
            Update
          </button>

          <button (click)="deleteProduct(product.id)">
            Delete
          </button>
        </td>
      </tr>

    }
  </tbody>
</table>

6. app.css

table {
  border-collapse: collapse;
  margin-top: 20px;
}

th,
td {
  padding: 10px;
}

button {
  margin: 5px;
  padding: 8px 12px;
}

7. main.ts

import { bootstrapApplication } from '@angular/platform-browser';
import { App } from './app/app';
import { appConfig } from './app/app.config';

bootstrapApplication(App, appConfig)
  .catch((error) => console.error(error));

How it works

The main flow is:

Component
   ↓
ProductService
   ↓
HttpClient
   ↓
REST API

The component should generally not contain the API URL or directly repeat HTTP logic. The reusable HTTP operations are placed in ProductService.

GET

getProducts(): Observable<Product[]> {
  return this.http.get<Product[]>(this.apiUrl);
}

Request:

GET https://localhost:7001/api/products

The component subscribes:

this.productService.getProducts().subscribe({
  next: (data) => {
    this.products = data;
  },
  error: (error) => {
    console.error(error);
  }
});

POST

createProduct(product: Product): Observable<Product> {
  return this.http.post<Product>(
    this.apiUrl,
    product
  );
}

Request:

POST https://localhost:7001/api/products

Angular automatically serializes the object into JSON:

{
  "id": 0,
  "name": "Laptop",
  "price": 75000
}

PUT

updateProduct(id: number, product: Product): Observable<void> {
  return this.http.put<void>(
    `${this.apiUrl}/${id}`,
    product
  );
}

For:

updateProduct(10, product)

the request becomes:

PUT https://localhost:7001/api/products/10

with the product object sent in the request body.

DELETE

deleteProduct(id: number): Observable<void> {
  return this.http.delete<void>(
    `${this.apiUrl}/${id}`
  );
}

For:

deleteProduct(10)

Angular sends:

DELETE https://localhost:7001/api/products/10

Most important syntax

// GET
this.http.get<Product[]>(url);

// GET by ID
this.http.get<Product>(`${url}/${id}`);

// POST
this.http.post<Product>(url, product);

// PUT
this.http.put<void>(`${url}/${id}`, product);

// DELETE
this.http.delete<void>(`${url}/${id}`);

And for standalone Angular, don't forget:

provideHttpClient()

in app.config.ts.

← Back to Articles