John_ John_ - 1 month ago 12
C# Question

Validation datacontract and datamember required

I'm using the web api to build an API and when receiving the posted values and binding them to my model I get an error that seems out of place.

I have a simple model exactly as below:

public class Client
{
[ScaffoldColumn(false)]
[JsonIgnore]
public int ClientID { get; set; }
[Required, StringLength(75)]
public string Name { get; set; }
[Required]
public bool Active { get; set; }
}


When sending this model through into my post method on my controller

public object Post([FromBody]Client postedClient)


it goes through the x-www-form-urlencoded formatter but it throws:

Property 'Active' on type 'CreditSearch.Api.Models.Rest.Client' is invalid. Value-typed properties marked as [Required] must also be marked with [DataMember(IsRequired=true)] to be recognized as required. Consider attributing the declaring type with [DataContract] and the property with [DataMember(IsRequired=true)].


I also tried it send the same data in json format but I get the same result. I tried to add these attributes just to get the code working but Resharper and myself cannot find the correct reference. Even so I'd prefer not to add this superfluousness attributes that haven't been required before when validating in a plain MVC system.


  1. Do I really need these attributes? They weren't required before.

  2. If so what references do I need to add?


Answer

The reason this validation is there is because for reference-typed members, whenever the member is deserialized WebAPI can check that the member is not null. For value types, there is no null value so it's up to the formatter to check that the value is present in the request body. Unfortunately, our XML formatter doesn't support the [Required] attribute so it won't raise a model state error if the member is missing.

If you're OK with certain formatters not raising model state errors for the missing value-typed members, you can use this line to remove the validation:

config.Services.RemoveAll(typeof(ModelValidatorProvider), (provider) => provider is InvalidModelValidatorProvider);