Reputation: 29668
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
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
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
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