Lloyd
Lloyd

Reputation: 29668

Cannot serialise to XML in ASP.NET Core 2

I'm very confused at the moment with a basic ASP.NET Core 2 API project and content negotiation and returning something other than JSON.

I've had this working before in a 1.1 project but not in a 2. I basically want to return something either as JSON or XML depending on request type.

As part of that requirement I set up the XML formatter like so:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc(options =>
        {
            options.ReturnHttpNotAcceptable = true;
            options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
        });
    }

I could also use AddXmlSerializerFormatters() but same difference (and tried). This is the way I've seen in countless examples and done before.

I have a single controller and single action, basically looks like:

[Route("api/[controller]")]
public class DefaultController : Controller
{
    [HttpGet]
    [Route("")]
    public IActionResult Index()
    {
        return Ok(new
        {
            success = true
        });
    }
}

Now when I run I get this back in Postman:

{"success": true}

So it works (or at least defaults) to JSON.

Then if I request using the header Accept: application/xml instead I now get a HTTP error of 406.

If I take off options.ReturnHttpNotAcceptable = true;, it will return JSON regardless.

What am I missing? I'm sat scratching my head on this. As far as I know I've registered an acceptable content formatter.

Upvotes: 6

Views: 2853

Answers (3)

uzay95
uzay95

Reputation: 16632

As @So used to be good said, anonymous types can't be serialized into XML. Here is my example:

[AllowAnonymous]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class ProducesResponseFormatController : ControllerBase {
    [HttpGet]
    [Produces("application/xml")]
    public IActionResult Get() {
        // this worked well
        return Ok(new Model.appsettings.TokenSettings()); 

        // this didn't
        return Ok(new { A = new { B = "b inside a", C = "C inside A" }, D = "E" }); 
    }
}

Upvotes: 0

zxczzx
zxczzx

Reputation: 11

There is already open issue for that.

As a workaround try adding this option to Mvc:

options.FormatterMappings.SetMediaTypeMappingForFormat("xml", "text/xml");

with [FormatFilter] attribute

Upvotes: 1

Camilo Terevinto
Camilo Terevinto

Reputation: 32068

The problem you are seeing is that anonymous types cannot be serialized into XML, so the formatter fails and falls back to the JSON formatter.

Solution: use classes when you need to return XML.

Upvotes: 9

Related Questions