I know this has been asked here and at various other places but I have not seen a simple answer. Or at least, I have not been able to find any.
In short, I have an .Net Core Web Api endpoint that accepts XML. Using (in Startup):
services.AddControllers().AddXmlSerializerFormatters();
I want to modelbind it to a class. Example:
[Route("api/[controller]")]
[ApiController]
public class PersonController : ControllerBase
{
[HttpPost]
[Consumes("application/xml")]
[ApiConventionMethod(typeof(DefaultApiConventions), nameof(DefaultApiConventions.Post))]
public async Task<ActionResult> PostPerson([FromBody] Person person)
{
return Ok();
}
}
// Class/Model
[XmlRoot(ElementName = "Person")]
public class Person
{
[XmlElement(ElementName = "Name")]
public string Name { get; set; }
[XmlElement(ElementName = "Id")]
public int Id { get; set; }
}
Passing in:
<Person><Name>John</Name><Id>123</Id></Person>
works fine. However, as soon as namespaces comes into play it either fails to bind the model:
<Person xmlns="http://example.org"><Name>John</Name><Id>123</Id></Person>
<Person xmlns="http://example.org"><Name>John</Name><Id xmlns="http://example.org">123</Id></Person>
Or the model can be bound but the properties are not:
<Person><Name xmlns="http://example.org">John</Name><Id>123</Id></Person>
<Person><Name xmlns="http://example.org">John</Name><Id xmlns="http://example.org">123</Id></Person>
etc.
I understand namespaces. I do realize that I can set the namespaces in the XML attribute for the root and elements. However, I (we) have a dozens of callers and they all set their namespaces how they want. And I want to avoid to have dozens of different versions of the (in the example) Person classes (one for each caller). I would also mean that if a caller changes their namespace(s) I would have to update that callers particular version and redeploy the code.
So, how can I modelbind incoming XML to an instance of Person without taking the namespaces into account?
I've done some tests overriding/creating an input formatter use XmlTextReader and set namespaces=false:
XmlTextReader rdr = new XmlTextReader(s);
rdr.Namespaces = false;
But Microsoft recommdes to not use XmlTextReader since .Net framework 2.0 so would rather stick to .Net Core (5 in this case).
