I'm (trying) to upgrade ASP.NET Core application from .NET Core App 3.1 to .NET 6 but one test fails that deserialize a Problem result. Reason for failing is that in .NET 6 the content type is application/problem+json
whilst in .NET Core App 3.1 application/xml
.
Have searched for any notes regarding this in migration document but can't find anything.
A repro is available in my GitHub and the controller is very simple
using System.Net.Mime;
using Microsoft.AspNetCore.Mvc;
namespace ProblemDetailsXMLSerialization
{
[ApiController]
[Route("[controller]")]
public class XmlController : ControllerBase
{
[HttpPost]
[Produces(MediaTypeNames.Application.Xml)]
[Consumes(MediaTypeNames.Application.Xml)]
public IActionResult Xml()
{
return Problem();
}
}
}
// Test file
using Microsoft.AspNetCore.Mvc.Testing;
using ProblemDetailsXMLSerialization;
using System.Net.Http;
using System.Net.Mime;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace TestProject1
{
public class UnitTest1
{
[Fact]
public async Task Test1()
{
// Arrange
var application = new WebApplicationFactory<Startup>();
var client = application.CreateClient();
// Act
const string xml = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>";
var content = new StringContent(xml, Encoding.UTF8, MediaTypeNames.Application.Xml);
var response = await client.PostAsync("xml", content);
// Assert
Assert.Equal(MediaTypeNames.Application.Xml, response.Content.Headers.ContentType.MediaType);
var responseString = await response.Content.ReadAsStringAsync();
}
}
}
Thanks
To get an XML
response - matching your assert statement - you'll need to add an Accept
HTTP header with value application/xml
.
From the documentation:
Content negotiation occurs when the client specifies an
Accept
header. The default format used by ASP.NET Core isJSON
.
var content = new StringContent(xml, Encoding.UTF8, MediaTypeNames.Application.Xml);
client.DefaultRequestHeaders.Add(
"Accept", "application/xml"
);
var response = await client.PostAsync("xml", content);
There are built-in strings for both Accept
and application/xml
.
client.DefaultRequestHeaders.Add(
Microsoft.Net.Http.Headers.HeaderNames.Accept,
System.Net.Mime.MediaTypeNames.Application.Xml
);
Setting that header to the DefaultRequestHeaders
makes it being sent with every request made by that HttpClient
instance.
In case you only want/need it for a single request, then use a HttpRequestMessage
instance.
using (var request = new HttpRequestMessage(HttpMethod.Post, "xml"))
{
request.Headers.Add("accept", "application/xml");
request.Content = new StringContent(xml, Encoding.UTF8, MediaTypeNames.Application.Xml);
var response = await client.SendAsync(request);
var responseString = await response.Content.ReadAsStringAsync();
}
In either case, the responseString
variable will contain an xml payload similar to below one.
<problem xmlns="urn:ietf:rfc:7807">
<status>500</status>
<title>An error occurred while processing your request.</title>
<type>https://tools.ietf.org/html/rfc7231#section-6.6.1</type>
<traceId>00-26c29d0830bd0a5a417e9bab9746bd23-3cfbc9589ffd8182-00</traceId>
</problem>