I have an ASP.NET Core 8 Web API built with C#, and I'd like to add some validations to the request body for PUT operations. One of it is to ensure that requests coming to my API is matching exactly my UpdateProductRequest model structure.
See sample code snippet below:
public class UpdateProductRequest
{
[Required]
public string Name { get; set; }
public string Description { get; set; }
}
[HttpPut]
public async Task<IActionResult> UpdateProduct([Required][FromRoute] int productId, [Required][FromBody] UpdateProductRequest updateProductRequest)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// ... do stuff
return Accepted();
}
Now, here are some scenarios I'd like to handle:
Valid:
{
"name": "Product A"
}
{
"name": "Product A",
"description": "some product description"
}
Invalid:
{
"name": "Product A",
"descriptionOfProduct": "some data"
}
{
"name": "Product A",
"somethingElse": "some data"
}
{
"name": "Product A",
"": "some data"
}
This is also invalid but will be handled just fine by the ModelState.IsValid
{
"names": "Product A",
"description": "some product description"
}
I have tried a few things already like writing a custom checker to read the request body using a StreamReader, but I'm getting an error reading the JSON from the request body:
The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true
var jsonString = await new StreamReader(bindingContext.HttpContext.Request.Body).ReadToEndAsync();
// Deserialize the JSON into a dictionary
var jsonDoc = JsonDocument.Parse(jsonString);
var jsonElement = jsonDoc.RootElement;
// Get the properties of the model type
var modelProperties = typeof(T).GetProperties();
var modelPropertyNames = new HashSet<string>(modelProperties.Select(p => p.Name.ToLowerInvariant()));
// Check for extra properties
foreach (var property in jsonElement.EnumerateObject())
{
if (!modelPropertyNames.Contains(property.Name.ToLowerInvariant()))
{
bindingContext.ModelState.AddModelError(property.Name, $"The property '{property.Name}' is not allowed.");
}
}
Any idea what I'm doing wrong or any suggestions how to validate this properly and efficiently? Please help as I'm going around in circles with this validation problems.

"name": ""- valid or no? Also, if this kind of validation is not working as you expect, I'd recommend considering FluentValidation.