I have a Asp.Net 6+ Web Api that has two endpoints doing almost exactly the same thing :
- the first one gets its parameters automagically from Asp.Net . I didn't give it a second thought: it accepts parameters from the POST's body and it's Asp.Net that does the deserialization, via System.Text.Json internally.
[HttpPost]
[Route("public/v1/myRoute/")]
public async Task<ActionResult> Import(IEnumerable<JsonItemModel> items) {
// the items are already ready to use.
FooProcessItems(items);
}
- the second one receives an IFormFile in a form data (the end-user uploads a file by using a button in the UI), gets the stream, and deserializes it "manually" using System.Text.JsonSerializer.DeserializeAsync.
[HttpPost]
[Route("public/v1/myRouteWithFile/")]
public async Task<ActionResult<Guid>> ImportWithFile([FromForm] MyFormData formData
) {
var stream = formaData.File.OpenReadStream();
var items = await JsonSerializer.DeserializeAsync<IEnumerable<JsonItemModel>>(file);
FooProcessItems(items);
}
My question :
I want to customize the deserialization process (to add some constraints such as "this field cannot be null", etc.) and I want both methods to produce exactly the same result.
How do I do that?
Is it simply a case of adding Json decorators in the model and letting .Net do the rest?
public class JsonItemModel {
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)] // <-- Some custom constraint that will be picked up both by Deserialize and the POST endpoint.
public int SomeField { get; init; } = 0;
...
}