ASP.NET Core – How to receive requests with XML content

Receiving requests with XML content is straightforward. You have to register the built-in XML InputFormatter (otherwise you get 415 – Unsupported Media Type errors). When a request comes in with an XML Content-Type (such as application/xml), it uses this InputFormatter to deserialize the request body XML.

In this article, I’ll show step-by-step how to receive a request with XML by registering the built-in XML InputFormatter, adding a model class, and configuring the action method.

Note: There are actually two XML InputFormatters to pick from. One that uses XmlSerializer and one that uses DataContractSerializer. I prefer XmlSerializer since it’s easier to use.

1 – Register the XML InputFormatter

In the initialization code, call AddXmlSerializerFormatters() to register the built-in XML InputFormatter:

using Microsoft.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers().AddXmlSerializerFormatters();

//the rest of the initialization code
Code language: C# (cs)

This essentially adds the built-in XmlSerializerInputFormatter class to the collection of InputFormatters. Note: It also adds the XML output formatter, which you need for returning XML responses.

2 – Add a model class

Add a model class that matches the XML structure:

public class Recipe
{
	public string Name { get; set; }
	public int Servings { get; set; }
}
Code language: C# (cs)

Note: Property order doesn’t matter when you use XmlSerializer and no attributes are required.

3 – Configure the action method

Now add the model class as a parameter on the action method and optionally add the [Consumes] attribute:

[HttpPost()]
[Consumes("application/xml")] //OPTIONAL: this constrains it to only allow XML
public IActionResult Post(Recipe recipe)
{
	return Ok($"Posted recipe {recipe.Name}");
}
Code language: C# (cs)

The Recipe is a complex type, so it’s implicitly bound to the request body (don’t need to annotate it with [FromBody]).

Note: You don’t need to add [Consumes(“application/xml”)] to get it to work with XML. This attribute is used to constrain the allowed Content-Types. If you don’t add this, the client can actually send the request as either JSON or XML, so it’s more flexible.

Example of sending an XML request

Now send a request to this endpoint with XML in the request body.

POST /Recipe

Content-Type: application/xml

Body:
<Recipe>
    <Name>Pizza</Name>
    <Servings>4</Servings>
</Recipe>Code language: plaintext (plaintext)

Read more about sending requests with Postman.

Because the XML InputFormatter is registered, it’s able to deserialize the XML request body. This returns a 200 (OK) response with the following output:

Posted recipe PizzaCode language: plaintext (plaintext)