I am builing an Api using the JsonPatch Document described here:
JsonPatch in ASP.NET Core web API
I have the following method in my controller:
[HttpPatch("{id:int}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult> Patch(int id, [FromBody] JsonPatchDocument<ClientDto> clientPatch)
{
Client? client = await _clientRepository.GetClientAsync(id);
if (client != null)
{
ClientDto clientDto = _mapper.Map<ClientDto>(client);
clientPatch.ApplyTo(clientDto, ModelState);
if(ModelState.IsValid)
{
_mapper.Map(clientDto, client);
await _clientRepository.UpdateClientAsync(client);
return NoContent();
}
return BadRequest();
}
return NotFound();
}
And the following DTO:
public record ClientDto
{
public int? Id { get; set; }
[Required]
[StringLength(50, MinimumLength = 1)]
public required string Name { get; set; }
}
When testing my implementation, I am expecting the following PATCH request to result in an invalid Model and therefore a 400 response:
[
{
"path": "/name",
"op": "replace",
"value": "Changed"
}
]
However, during testing, the ModelState remains Valid when sending the above Patch. Can anyone advise what I am doing wrong?
There is the ControllerBase.TryValidateModel(object)
method that can be called once the changes have been applied to the model:
clientPatch.ApplyTo(clientDto, ModelState);
if(Model.IsValid && TryValidateModel(clientDto))
{
// Logic when valid
return NoContent();
}
return ValidationProblem(ModelState);
If the model validation fails, returning theControllerBase.ValidationProblem(ModelStateDictionary)
method will also ensure the response is consistant with the default middleware validation when using Data Annotations.