2

In my Startup.ConfigureServices method I have:

services.AddMvc(setupAction =>
{
     setupAction.ReturnHttpNotAcceptable = true;

     setupAction.OutputFormatters.Add(new XmlSerializerOutputFormatter());
     setupAction.InputFormatters.Add(new XmlSerializerInputFormatter());
});

I've also tried:

services.AddMvc(setupAction =>
{
    setupAction.ReturnHttpNotAcceptable = true;

    setupAction.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
    setupAction.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());
});

My POST method's signature looks like:

[HttpPost("xunit")]
public IActionResult PostXunitResults([FromBody] XunitResult results)

XunitResult looks like:

[Serializable]
[XmlRoot("assemblies")]
public class XunitResult
{
    [XmlIgnore]
    public const string MimeType = "application/xml";

    [XmlAttribute("timestamp")]
    public string Timestamp { get; set; }

    [XmlElement("assembly")]
    public List<Assembly> Assemblies { get; set; }
}

[Serializable]
[XmlType("assembly")]
public class Assembly
{
...

With this setup I can run tests to check that my model deserializes the XML correctly:

    [Fact]
    public void WhenYouDeserializeXunitResultsIntoAnXunitResultsObject_ThenTheObjectIsPopulatedCorrectly()
    {
        var serializer = new XmlSerializer(typeof(XunitResult));
        XunitResult results;
        using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(_xunitResults)))
        {
            results = (XunitResult)serializer.Deserialize(stream);
        }
        results.Assemblies.Should().NotBeNull();
    }

... which it does.

When I try to use XunitResult as a [FromBody] argument to the post method, the model is not rendered correctly in Swagger:

  1. Swagger does not display XunitResult correctly in the example, it renders the root as 'XunitResult' instead of 'assemblies' as defined in the XMLRootAttribute on XunitResult.
  2. Also, the same model does not render the Timestamp property in XunitResult as an attribute, it renders it as an element. This is just an example. The other XmlAttributes in the class are rendered as elements as well, and not as attributes like they should be.
  3. The assemblies element is rendered as an assembly should be if it were inside of the assemblies element.

view screenshot for the above 2 items here

The XML model should look similar to this:

<?xml version="1.0" encoding="utf-8"?>
<assemblies timestamp="02/27/2018 14:32:47">
  <assembly name="API.Test.dll" environment="64-bit .NET Standard [collection-per-class, parallel (8 threads)]" test-framework="xUnit.net 2.3.1.3858" run-date="2018-02-27" run-time="14:32:47" total="9" passed="5" failed="3" skipped="1" time="0.161" errors="0">
    <errors />
    <collection total="1" passed="0" failed="1" skipped="0" name="Test collection for API.Test.API.Results.TestResultPost2" time="0.000">
      <test name="API.Test.API.Results.TestResultPost2.TestWeWontGetTo" type="API.Test.API.Results.TestResultPost2" method="TestWeWontGetTo" time="0" result="Fail">
        <failure exception-type="System.Exception">
          <message><![CDATA[System.Exception : exception in setup]]></message>
          <stack-trace><![CDATA[   at API.Test.API.Results.TestResultPost2..ctor() in /Users//Documents///API.Test/Controller/TestResultsPost.cs:line 60]]></stack-trace>
        </failure>
      </test>
    </collection>
...

And when I try to post XML according to the model in swagger, OR if I try to post valid XML, the results variable in the PostXunitResults method is null.

If I inspect the body of the call via Request.Body, then the first part of the XML that I posted is gone, only the last part is in the Body stream.

Any help to figure this out would be great!

Kaman Poole
  • 87
  • 1
  • 10
  • Most likely issue is related to your model. Try with simple model (say just XunitResult with Timestamp, without assemblies) and see if you observe the same result. If not - post full model and full xml you are posting. – Evk Apr 02 '18 at 19:41
  • Using the example here: https://stackoverflow.com/questions/12924221/using-xmlserializer-with-an-array-in-the-root-element/12924341, I tried posting `` to a method with a parameter of the ScanDetails type, and that resulted in a non-null argument. Thanks for helping me to think to simplify the model in order to step through the problem. Swagger still does not render the model correctly, but that is not as important right now. – Kaman Poole Apr 02 '18 at 21:11
  • Check `this.ModelState.IsValid` in your `PostXunitResults`. If it's false - inspecting that model state might give you some clues about what exactly asp.net doesn't like about what you post (and why it thinks it does not match the model). – Evk Apr 02 '18 at 21:15

0 Answers0