Tutorials ASP.NET Core Web API

Content Negotiation (JSON vs XML)

On this page

Content Negotiation (JSON vs XML)

ASP.NET Core Web API does not force clients to consume JSON. By relying on Content Negotiation, your API can dynamically look at an incoming HTTP request, see what format the client prefers, and automatically format the response data into JSON, XML, or even custom binary formats without altering your Controller logic.

1. The "Accept" Header

Content negotiation triggers when the client sends an Accept HTTP Header with their request.

  • Accept: application/json (The web industry default)
  • Accept: application/xml (Used heavily in legacy enterprise systems/SOAP integrations)

2. Enabling XML Formatters

By default, the ASP.NET Core Web API template only ships with the JSON Formatter enabled. If a client requests XML, the pipeline simply ignores the request and forces JSON anyway. You must explicitly configure the MVC pipeline to respect XML demands.

// Program.cs
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers(options =>
{
    // If a client requests a format we DON'T support (e.g. application/pdf),
    // ASP.NET Core will return JSON anyway. True REST APIs should instead 
    // reject the request by returning a 406 Not Acceptable status code.
    options.ReturnHttpNotAcceptable = true; 
})
// This single line enables full bi-directional XML support
.AddXmlDataContractSerializerFormatters(); 

3. Enforcing Specific Formats per Endpoint

While global content negotiation is powerful, there are times when an endpoint generates a file specifically designed for one format (e.g., generating an XML Sitemap for Google SEO). You can override negotiation using the [Produces] attribute.

[ApiController]
[Route("api/sitemap")]
public class SeoController : ControllerBase
{
    [HttpGet]
    [Produces("application/xml")] // Forces the output to be XML, skipping negotiation
    public IActionResult GenerateSitemap()
    {
        var urls = _repo.GetSitemapUrls();
        return Ok(urls); 
    }
}

4. Interview Mastery

Q: "The client sends `Accept: application/xml`, but our API is still returning JSON. Furthermore, we enabled `AddXmlDataContractSerializerFormatters()`. Why is the format still JSON?"

Architect Answer: "The issue almost always lies in the payload itself. If you return an anonymous internal C# object (e.g., `return Ok(new { msg = 'Success' })`), the JSON serializer handles it beautifully because JSON has no rigid structural schema rules. However, XML is strongly typed. The XML Serializer physically cannot serialize an anonymous class because it doesn't know what to name the root XML Node. Whenever XML serialization fails silently, ASP.NET Core gracefully falls back down the chain to the default JSON formatter. To fix it, you MUST return a concrete named class (e.g., a DTO) instead of an anonymous type."

Questions on this lesson 0

Sign in to ask a question or upvote helpful answers.

No questions yet — be the first to ask!

ASP.NET Core Web API
Course syllabus
1. Fundamentals & HTTP
2. Request Handling
3. Data Access & Architecture
4. Data Transfer & Validation
5. Advanced Concepts
6. Security & Authorization
7. Documentation & Testing
8. Microservices & Deployment
Toolliyo Assistant
Ask about tutorials, ebooks, training, pricing, mentor services, and support. I use public site content only—not admin or internal tools.

care@toolliyo.com

Need callback? Share your details