- Swashbuckle Pro Tips for ASP.NET Web API – Content Types
- Swashbuckle Pro Tips for ASP.NET Web API – Example/s Using AutoFixture
- Swashbuckle Pro Tips for ASP.NET Web API – XML
In the previous post, we implemented IOperationFilter
of Swashbuckle to handle example objects with combination of AutoFixture. According to Swagger spec, it doesn’t only handle JSON payloads, but also copes with XML payloads. In this post, we’re going to use the Swashbuckle library again to handle XML payloads properly.
The sample codes used in this post can be found here.
Acknowledgement
The sample application uses the following spec:
Built-In XML Support of Web API
ASP.NET Web API contains the Httpconfiguration
instance out-of-the-box and it handles both JSON and XML payloads serialisation/deserialisation. Therefore, without any extra efforts, we can see those Swagger UI pages showing both JSON and XML payload.
As Swashbuckle is a JSON-biased library, camelCasing
in JSON payloads is well supported, while XML payloads is not. All XML nodes is PascalCasing
, which is inconsistent. How can we support camel-case on both JSON and XML? Here’s the tip:
It’s a little bit strange that, in order for XML to support camel-casing, we should change JSON serialisation settings, by the way. Go back to the Swagger UI screen and we’ll be able to find out all XML nodes except the root one are now camel-cased. The root node will be dealt later on.
Let’s send a REST API request to the endpoint using an XML payload.
However, the model
instance is null
! The Web API action can’t recognise the XML payload.
This is because the HttpConfiguration
instance basically uses the DataContractSerializer
instance for payload serialisation/deserialisation, but this doesn’t work as expected. What if we change the serialiser to XmlSerializer
from DataContractSerializer
? It would work. Add the following a line of code like:
Go back to the screen again and we’ll confirm the same screen as before.
What was the change? Let’s send an XML request again with some value modifications.
Now, the Web API action recognises the XML payload, but something weird happened. We sent lorem ipsum
and 123
, but they’re not passed. What’s wrong this time? There might be still the casing issue. So, instead of camel-cased payload, use pascal-cased XML payload and see how it’s going.
Here we go! Now the API action method can get the XML payload properly!
In other words, Swagger UI screen showed the proper camel-cased payload, but in fact it wasn’t that payload. What could be the cause? Previously we set the UseXmlSerializer
property value to true
for nothing. Now, all payload models should have XmlRoot
and/or XmlElement
decorators. Let’s update the payload models like:
Send the XML request again and we’ll get the payload!
However, it’s still not quite right. Let’s have a look at the actual payload and example payload.
The example payload defines ValueRequestModel
as a root node. However, the actual payload uses request
as declared in the XmlRoot
decorator. Where should I change it? Swagger spec defines the xml
object for this case. This can be easily done by implementing the ISchemaFilter
interface of Swashbuckle.
Defining xml
in Schema Object
Here’s the sample code defining the request
root node by implementing the ISchemaFilter
interface.
It applies the Visitor Pattern to filter out designated types only.
Once implemented, Swagger configuration needs to include the filter to register both ValueRequestModel
and ValueResponseModel
so that the request model has request
on its root node and the response model has response
on its root node. Try the Swagger UI screen again.
Now the XML payload looks great and works great.
So far, we’ve briefly walked through how Swagger document deals with XML payloads, using Swashbuckle.