Headers and Content Types
🎯 What You'll Learn
- Common HTTP headers
- Content-Type and Accept headers
- Content negotiation
- Custom headers
- CORS headers
- How to read and set headers in ASP.NET Core
- Complete InvenTrack examples
What are HTTP Headers?
HTTP headers are key-value pairs that provide metadata about the request or response.
GET /api/products HTTP/1.1
Host: inventrackapp.com
User-Agent: Mozilla/5.0
Accept: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
Common Request Headers
| Header | Purpose | Example |
|---|---|---|
| Host | Target server | inventrackapp.com |
| User-Agent | Client information | Mozilla/5.0 |
| Accept | Expected response format | application/json |
| Content-Type | Format of request body | application/json |
| Authorization | Authentication credentials | Bearer token... |
| Cookie | Cookies sent to server | sessionId=abc123 |
Common Response Headers
| Header | Purpose | Example |
|---|---|---|
| Content-Type | Format of response body | application/json |
| Content-Length | Size of response body | 1234 |
| Location | URL of created resource | /api/products/123 |
| Set-Cookie | Set cookie in browser | sessionId=abc123 |
| Cache-Control | Caching directives | no-cache |
| Access-Control-Allow-Origin | CORS policy | * |
Content-Type Header
Content-Type specifies the format of the request/response body.
Common Content Types
| Content-Type | Description | Use Case |
|---|---|---|
application/json |
JSON data | APIs (most common) |
application/xml |
XML data | Legacy APIs, SOAP |
text/html |
HTML document | Web pages |
text/plain |
Plain text | Simple text responses |
multipart/form-data |
Form with files | File uploads |
application/x-www-form-urlencoded |
Form data | HTML forms |
POST /api/products HTTP/1.1
Content-Type: application/json
{
"name": "Laptop",
"price": 999.99
}
Content Negotiation
Content negotiation allows clients to request different response formats using the
Accept header.
GET /api/products/123 HTTP/1.1
Accept: application/json
GET /api/products/123 HTTP/1.1
Accept: application/xml
Enable Content Negotiation in ASP.NET Core
builder.Services.AddControllers(options =>
{
options.RespectBrowserAcceptHeader = true; // Enable content negotiation
})
.AddXmlSerializerFormatters(); // Add XML support
Reading Headers in ASP.NET Core
[HttpGet]
public IActionResult GetProducts()
{
// Read specific header
var userAgent = Request.Headers["User-Agent"].ToString();
// Read Authorization header
var authHeader = Request.Headers["Authorization"].ToString();
// Check if header exists
if (Request.Headers.ContainsKey("X-API-Key"))
{
var apiKey = Request.Headers["X-API-Key"].ToString();
}
// Read Content-Type
var contentType = Request.ContentType;
return Ok();
}
Using [FromHeader] Attribute
[HttpGet]
public IActionResult GetProducts(
[FromHeader(Name = "X-API-Key")] string apiKey,
[FromHeader(Name = "X-Request-Id")] string? requestId = null)
{
// apiKey and requestId are automatically bound from headers
return Ok();
}
Setting Response Headers
[HttpGet]
public IActionResult GetProducts()
{
// Set custom headers
Response.Headers["X-Total-Count"] = "100";
Response.Headers["X-API-Version"] = "1.0";
Response.Headers["X-Response-Time"] = "45ms";
// Set Cache-Control
Response.Headers["Cache-Control"] = "no-cache";
return Ok(new List<Product>());
}
Custom Headers
Custom headers should start with X- (convention).
Common Custom Headers
X-API-Key: API authenticationX-Request-Id: Request trackingX-Correlation-Id: Distributed tracingX-Total-Count: Total items in paginated responseX-Response-Time: Server processing time
[HttpGet]
public async Task<IActionResult> GetProducts(
[FromQuery] int page = 1,
[FromQuery] int pageSize = 10)
{
var result = await _productService.GetPagedAsync(page, pageSize);
// Add pagination headers
Response.Headers["X-Total-Count"] = result.TotalCount.ToString();
Response.Headers["X-Page"] = page.ToString();
Response.Headers["X-Page-Size"] = pageSize.ToString();
Response.Headers["X-Total-Pages"] = result.TotalPages.ToString();
return Ok(result.Items);
}
CORS Headers
CORS (Cross-Origin Resource Sharing) headers allow browsers to make cross-origin requests.
Common CORS Headers
Access-Control-Allow-Origin: Allowed originsAccess-Control-Allow-Methods: Allowed HTTP methodsAccess-Control-Allow-Headers: Allowed headersAccess-Control-Allow-Credentials: Allow cookies
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowFrontend", policy =>
{
policy.WithOrigins("https://inventrackapp.com")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
});
var app = builder.Build();
app.UseCors("AllowFrontend");
Complete InvenTrack Example
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}
// Pagination with custom headers
[HttpGet]
public async Task<IActionResult> GetProducts(
[FromQuery] int page = 1,
[FromQuery] int pageSize = 10)
{
var result = await _productService.GetPagedAsync(page, pageSize);
// Add pagination headers
Response.Headers["X-Total-Count"] = result.TotalCount.ToString();
Response.Headers["X-Page"] = page.ToString();
Response.Headers["X-Page-Size"] = pageSize.ToString();
Response.Headers["X-Total-Pages"] = result.TotalPages.ToString();
return Ok(result.Items);
}
// API Key from header
[HttpGet("secure")]
public IActionResult GetSecureData(
[FromHeader(Name = "X-API-Key")] string apiKey)
{
if (apiKey != "secret-key-123")
return Unauthorized();
return Ok("Secure data");
}
// Content negotiation (JSON/XML)
[HttpGet("{id}")]
[Produces("application/json", "application/xml")]
public async Task<IActionResult> GetProduct(int id)
{
var product = await _productService.GetByIdAsync(id);
if (product == null)
return NotFound();
// Returns JSON or XML based on Accept header
return Ok(product);
}
// File upload (multipart/form-data)
[HttpPost("upload")]
public async Task<IActionResult> UploadImage(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest("No file uploaded");
// Check Content-Type
if (!file.ContentType.StartsWith("image/"))
return BadRequest("Only images allowed");
var url = await _productService.UploadImageAsync(file);
return Ok(new { imageUrl = url });
}
}
Key Takeaways
- Headers: Key-value pairs with request/response metadata
- Content-Type: Format of request/response body
- Accept: Client's preferred response format
- Content negotiation: Return different formats (JSON/XML)
- Custom headers: Start with
X-(e.g.,X-API-Key) - CORS headers: Enable cross-origin requests
- Read headers with
Request.Headers - Set headers with
Response.Headers - Use
[FromHeader]to bind headers to parameters - Use
[Produces]for content negotiation
You now understand HTTP headers and content types! In the final section, we'll explore Cookies and Sessions—how to maintain state across requests, session management, and cookie security.