I have an Mvc core web api with a simple Post method.
Case Model:
public class Case {
[Required]
public string CaseReference { get; set; }
[Required]
public string Title{ get; set; }
[Required]
public string Forename{ get; set; }
[Required]
public List<Address> Addresses { get; set; }
}
Address Model:
public class Address {
[Required]
[StringLength(8, MinimumLength = 5)]
public string Postcode{ get; set; }
[Required]
public string Town{ get; set; }
}
Controller Action:
public IActionResult Post([FromBody] Case item)
{
if (item == null)
{
return BadRequest(new ErrorMessage
{
Message = "Request object is empty",
StatusCode = 400
});
}
// This works and validates only the Case object but doesn't validate the
// Address object inside the Case object
var validationContext = new ValidationContext(item, null, null);
var validationResults = new List<ValidationResult>();
Validator.TryValidateObject(item, validationContext, validationResults, true);
// This always says the model is valid
var isValid = TryValidateModel(item);
// This always says the model is valid
if (!ModelState.IsValid)
{
return BadRequest(new ErrorMessage
{
Message = "ModelState is not valid. Check the ModelState property for specific errors.",
StatusCode = 400,
ModelState = ModelState.ToDictionary()
});
}
// model is fine so do some processing here
return Ok();
}
Using Postman I post the following:
{
"CaseReference":"ABC123",
"Addresses": [{"Postcode":"a"}]
}
How can i post a json Case object to this controller action and have ModelState validate it and show correctly that for example "Title" and "Forename" are required and also to validate the properties of the Address object that are missing e.g. "Town".
I would really appreciate some help with the above issue.
What is ModelState.IsValid before calling TryValidateModel()? That call should not be necessary and will likely confuse things.
I commented out all code above the ModelState.IsValid in case it confuses things and it is valid (true) when it shouldn't be. I started with ModelState.IsValid and it was always true. Then I tried above it with TryValidateModel and that was coming as valid and then added the Validator.TryValidateObject to see if that validates correctly.
Thanks for the added information
Apologies i should have added my Startup.cs file as well.
I have managed to make some progress and isolate what causes the issue.
In my startup ConfigureServices when I use the services.AddMvcCore() then the ModelState.IsValid is always valid but when I use the services.AddMvc() then it validates correctly.
public void ConfigureServices(IServiceCollection services)
{
// This works
services.AddMvc();
// This doesnt work
services.AddMvcCore();
}
Is there something extra that i'm missing when using MvcCore instead of Mvc ? Can it be made to work with MvcCore instead of Mvc?
You need AddMvcCore().AddDataAnnotations(). https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.DataAnnotations/DependencyInjection/MvcDataAnnotationsMvcCoreBuilderExtensions.cs#L25
AddMvcCore() is minimal. If you're looking for something equivalent to old WebAPI you probably want AddMvcCore().AddJsonFormatters().AddAuthorization().AddDataAnnotations()
That's great. Thank you very much.
Glad we could help!
I was looking for a solution for 4 hours. I think this should be in the documentation.
Thanks @rynowak it really helped me.
Most helpful comment
You need
AddMvcCore().AddDataAnnotations(). https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.DataAnnotations/DependencyInjection/MvcDataAnnotationsMvcCoreBuilderExtensions.cs#L25AddMvcCore()is minimal. If you're looking for something equivalent to old WebAPI you probably wantAddMvcCore().AddJsonFormatters().AddAuthorization().AddDataAnnotations()