Angular HttpClient: Query-String Parameters and HTTP Headers
Angular HttpClient allows you to send both query-string parameters and HTTP headers when calling an ASP.NET Core Web API.
For example:
GET /api/products?category=Laptop&page=1
Authorization: Bearer <token>
These serve different purposes:
| Feature | Purpose | Example |
|---|---|---|
| Query parameters | Pass filtering/search/paging values | ?category=Laptop&page=1 |
| HTTP headers | Pass request metadata | Authorization: Bearer token |
Full Simple Sample Program
product.ts
export interface Product {
id: number;
name: string;
price: number;
}
product.service.ts
This example demonstrates both query parameters and HTTP headers.
import { inject, Injectable } from '@angular/core';
import {
HttpClient,
HttpHeaders,
HttpParams
} 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';
// Query-string parameters
searchProducts(
category: string,
page: number
): Observable<Product[]> {
const params = new HttpParams()
.set('category', category)
.set('page', page);
return this.http.get<Product[]>(
this.apiUrl,
{ params }
);
}
// HTTP headers
getProductsWithHeaders(): Observable<Product[]> {
const headers = new HttpHeaders()
.set('Authorization', 'Bearer sample-token')
.set('X-Api-Key', '123456');
return this.http.get<Product[]>(
this.apiUrl,
{ headers }
);
}
// Query parameters + headers
searchProductsWithHeaders(
category: string,
page: number
): Observable<Product[]> {
const params = new HttpParams()
.set('category', category)
.set('page', page);
const headers = new HttpHeaders()
.set('Authorization', 'Bearer sample-token')
.set('X-Api-Key', '123456');
return this.http.get<Product[]>(
this.apiUrl,
{
params,
headers
}
);
}
}
1. How Do You Send Query-String Parameters?
What are Query-String Parameters?
Query-string parameters are values added to the end of a URL after ?.
For example:
https://localhost:7001/api/products?category=Laptop&page=1
Here:
category = Laptop
page = 1
Multiple parameters are separated using:
&
Therefore:
?category=Laptop&page=1
Using HttpParams
Angular provides:
HttpParams
from:
import { HttpParams } from '@angular/common/http';
Create parameters:
const params = new HttpParams()
.set('category', 'Laptop')
.set('page', 1);
Then pass them to HttpClient:
return this.http.get<Product[]>(
this.apiUrl,
{ params }
);
Angular constructs the URL appropriately:
GET /api/products?category=Laptop&page=1
Complete Query Parameter Method
searchProducts(
category: string,
page: number
): Observable<Product[]> {
const params = new HttpParams()
.set('category', category)
.set('page', page);
return this.http.get<Product[]>(
this.apiUrl,
{ params }
);
}
Call it:
this.productService
.searchProducts('Laptop', 1)
.subscribe({
next: (products) => {
console.log(products);
}
});
Angular sends:
GET https://localhost:7001/api/products?category=Laptop&page=1
ASP.NET Core Side
ASP.NET Core can receive these values using query binding:
[HttpGet]
public IActionResult GetProducts(
[FromQuery] string category,
[FromQuery] int page)
{
return Ok(new
{
Category = category,
Page = page
});
}
So the complete flow is:
Angular
↓
HttpParams
↓
category = Laptop
page = 1
↓
HttpClient.get()
↓
GET /api/products?category=Laptop&page=1
↓
ASP.NET Core
↓
[FromQuery]
↓
category = "Laptop"
page = 1
Simpler Modern Syntax
For simple parameters, you don't always need to explicitly create HttpParams.
You can also write:
return this.http.get<Product[]>(
this.apiUrl,
{
params: {
category: 'Laptop',
page: 1
}
}
);
This is convenient for simple cases.
For example:
searchProducts(
category: string,
page: number
): Observable<Product[]> {
return this.http.get<Product[]>(
this.apiUrl,
{
params: {
category: category,
page: page
}
}
);
}
Or using shorthand:
searchProducts(
category: string,
page: number
): Observable<Product[]> {
return this.http.get<Product[]>(
this.apiUrl,
{
params: {
category,
page
}
}
);
}
Both approaches are valid.
When Are Query Parameters Used?
Query parameters are commonly used for:
Searching
Filtering
Sorting
Pagination
Optional parameters
For example:
/api/products?search=laptop
/api/products?category=Electronics
/api/products?page=2&pageSize=20
/api/products?sortBy=price&sortOrder=desc
A real request might be:
GET /api/products
?search=laptop
&category=Electronics
&page=2
&pageSize=20
2. How Do You Send HTTP Headers?
What are HTTP Headers?
HTTP headers contain additional metadata about an HTTP request.
For example:
Authorization: Bearer eyJhbGciOi...
or:
X-Api-Key: abc123
Headers are commonly used for:
Authentication
Authorization
API Keys
Content negotiation
Correlation IDs
Custom metadata
Using HttpHeaders
Angular provides:
HttpHeaders
Import it:
import { HttpHeaders } from '@angular/common/http';
Create headers:
const headers = new HttpHeaders()
.set('Authorization', 'Bearer sample-token')
.set('X-Api-Key', '123456');
Then pass them:
return this.http.get<Product[]>(
this.apiUrl,
{ headers }
);
Complete Header Example
getProducts(): Observable<Product[]> {
const headers = new HttpHeaders()
.set(
'Authorization',
'Bearer sample-token'
)
.set(
'X-Api-Key',
'123456'
);
return this.http.get<Product[]>(
this.apiUrl,
{ headers }
);
}
The HTTP request conceptually becomes:
GET /api/products
Authorization: Bearer sample-token
X-Api-Key: 123456
ASP.NET Core Side
Suppose Angular sends:
X-Api-Key: 123456
ASP.NET Core can access it:
[HttpGet]
public IActionResult GetProducts()
{
var apiKey =
Request.Headers["X-Api-Key"].ToString();
return Ok();
}
For a custom header, you can also bind it explicitly:
[HttpGet]
public IActionResult GetProducts(
[FromHeader(Name = "X-Api-Key")] string apiKey)
{
return Ok();
}
Flow:
Angular
↓
HttpHeaders
↓
X-Api-Key: 123456
↓
HTTP Request
↓
ASP.NET Core
↓
[FromHeader]
↓
apiKey = "123456"
Sending a JWT Token
One of the most common uses of HTTP headers is authentication.
Suppose you have:
const token = 'eyJhbGciOi...';
Create the header:
const headers = new HttpHeaders()
.set(
'Authorization',
`Bearer ${token}`
);
Then:
return this.http.get<Product[]>(
this.apiUrl,
{ headers }
);
Request:
GET /api/products
Authorization: Bearer eyJhbGciOi...
ASP.NET Core authentication middleware can then validate the token.
Should We Add JWT Headers Manually Every Time?
Usually no.
Imagine you have 50 API methods:
getProducts()
getCategories()
getOrders()
getCustomers()
getUsers()
...
Repeating this everywhere:
const headers = new HttpHeaders()
.set(
'Authorization',
`Bearer ${token}`
);
would create duplicated code.
Instead, Angular commonly uses an HTTP interceptor.
Angular Service
↓
HttpClient
↓
Auth Interceptor
↓
Automatically adds JWT
↓
ASP.NET Core API
For example:
export const authInterceptor: HttpInterceptorFn =
(req, next) => {
const token = 'sample-token';
const newRequest = req.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next(newRequest);
};
Then configure it:
provideHttpClient(
withInterceptors([
authInterceptor
])
)
We'll normally use this approach for authentication headers in a real application.
Sending Query Parameters and Headers Together
You can send both in the same request.
searchProducts(
category: string,
page: number
): Observable<Product[]> {
const params = new HttpParams()
.set('category', category)
.set('page', page);
const headers = new HttpHeaders()
.set(
'Authorization',
'Bearer sample-token'
);
return this.http.get<Product[]>(
this.apiUrl,
{
params,
headers
}
);
}
The request becomes:
GET /api/products?category=Laptop&page=1
Authorization: Bearer sample-token
Notice where each value goes:
URL
↓
/api/products?category=Laptop&page=1
└───────────────┘
Query Params
HTTP Headers
↓
Authorization: Bearer sample-token
Query Parameters vs Headers
This distinction is important for interviews.
| Query Parameters | HTTP Headers |
|---|---|
| Part of URL | Part of HTTP metadata |
| Visible in URL | Not part of URL |
| Filtering | Authentication |
| Searching | JWT |
| Sorting | API keys |
| Pagination | Correlation IDs |
HttpParams |
HttpHeaders |
ASP.NET [FromQuery] |
ASP.NET [FromHeader] |
For example:
Filtering
↓
?category=Laptop
Pagination
↓
?page=2&pageSize=20
Whereas:
JWT
↓
Authorization: Bearer token
API Key
↓
X-Api-Key: 123456
Important: HttpParams and HttpHeaders Are Immutable
This is a useful Angular interview point.
Don't do this:
let params = new HttpParams();
params.set('category', 'Laptop');
params.set('page', 1);
set() returns a new HttpParams instance.
So use:
let params = new HttpParams();
params = params.set('category', 'Laptop');
params = params.set('page', 1);
Or, more commonly:
const params = new HttpParams()
.set('category', 'Laptop')
.set('page', 1);
The same concept applies to HttpHeaders.
Key Points
- Query parameters are passed through the
paramsoption.
this.http.get(url, { params });
- Angular provides
HttpParamsfor constructing query parameters.
const params = new HttpParams()
.set('category', 'Laptop')
.set('page', 1);
- HTTP headers are passed through the
headersoption.
this.http.get(url, { headers });
- Angular provides
HttpHeaders.
const headers = new HttpHeaders()
.set('X-Api-Key', '123456');
- You can send both together:
this.http.get(url, {
params,
headers
});
- Query parameters are commonly used for searching, filtering, sorting and pagination.
- Headers are commonly used for JWT tokens, API keys, correlation IDs and other request metadata.
HttpParamsandHttpHeadersare immutable.- For JWT authentication, prefer an HTTP interceptor rather than manually adding the header to every request.
Interview Questions and Answers
1. How do you send query-string parameters using Angular HttpClient?
Use the params option, commonly with HttpParams.
const params = new HttpParams()
.set('category', 'Laptop')
.set('page', 1);
return this.http.get<Product[]>(
this.apiUrl,
{ params }
);
This generates a URL such as:
/api/products?category=Laptop&page=1
2. How do you send HTTP headers?
Use the headers option with HttpHeaders.
const headers = new HttpHeaders()
.set('X-Api-Key', '123456');
return this.http.get<Product[]>(
this.apiUrl,
{ headers }
);
3. How does ASP.NET Core receive query parameters?
Using query binding:
[FromQuery] string category
For example:
public IActionResult Get(
[FromQuery] string category)
4. How does ASP.NET Core receive custom headers?
Using:
[FromHeader]
For example:
[FromHeader(Name = "X-Api-Key")]
string apiKey
5. What is the difference between query parameters and HTTP headers?
Query parameters are part of the URL and normally describe what data you want, such as filtering, searching or pagination.
Headers contain request metadata, such as authentication tokens, API keys and correlation IDs.
6. How do you send both parameters and headers?
return this.http.get<Product[]>(
this.apiUrl,
{
params,
headers
}
);
7. Should JWT headers be added manually to every request?
Usually no. An Angular HTTP interceptor is normally used to automatically attach the access token to applicable outgoing requests.
Short Interview Answer
In Angular, query-string parameters are sent through the
paramsoption, commonly usingHttpParams, while HTTP headers are sent through theheadersoption usingHttpHeaders. Query parameters are typically used for filtering, searching and pagination, whereas headers are commonly used for authentication, API keys and other request metadata.