I'm responsible for maintaining a public ASP.NET Core 8 Web API. One endpoint accepts POST data like this:
{
"xid": 12345,
"message": "Hello, world!"
}
On the .NET side, the controller action looks like this:
[HttpPost]
[Route("SendMessage")]
public async Task<ActionResult> SendMessage(MessageDto message)
{
// ...
}
And finally, MessageDto looks like this on the API side - importantly, the id field is a long:
public class MessageDto
{
public long XID { get; set; }
public string Message { get; set; }
}
The problem
Before I describe the problem, let me just emphasize that I did not originally write this code!
I'm being asked to change the API to support XID values that include a leading zero (for example, 06789). Obviously the correct answer here is to use a string for XID instead of a long, but since this is an active public API, I can't change the data contract.
Moreover, in ASP.NET Core Web API, JSON numbers with leading zeroes don't simply drop the zero. Instead, they throw a JSON parser error:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"$.xid": [
"Invalid leading zero before '6'. Path: $.xid | LineNumber: 1 | BytePositionInLine: 11."
]
}
}
I understand that this is because leading zeroes on whole numbers are simply not permitted in the JSON spec. Again, this field should have been a string from the get-go, but our users are already passing numbers.
What I've tried:
- Changing the property to a string on the API side: can't accept numbers anymore
- Writing a custom
JsonConverterfor type long: the "invalid leading zero" 400 is thrown before the converter is reached - Changing the property to a string and writing a custom
JsonConverterfor type string that turns long into string: the "invalid leading zero" 400 is thrown before the converter is reached
Given that I can't ask our users to change how they're submitting request data, is there any way to add custom handling for this field? Ideally, a solution would handle both number and string in the JSON (since it's possible some users will switch to submitting XID as a string because of the leading zero). But really, I just need some way to intercept this request before .NET decides it's bad JSON and returns a 400.
Alternately, is there a way to handle the query data as something other than JSON and avoid the parser entirely?
Thank you in advance for any and all advice!