1
votes

I have the following:

[DataContract]
public class Video
{
    [Key]
    [DataMember(IsRequired = false)]
    [Required]
    public int VideoId { get; set; }

    [DataMember(IsRequired = false)]
    [Required]
    public int UserId { get; set; }

    [Required]
    [DataMember(IsRequired=true)]
    public string Title { get; set; }

}

The goal here is to tell WebAPI via the DataMember decorations that all I need on the wire is Title - the other two properties are not required for a valid request.

I'm then trying to tell Entity Framework / SQL that the other properties are required in the database. I will assign them in my service or webapi layers.

If I use the following to send only the title, I get

{"$id":"1","message":"The request is invalid.","modelState":{"$id":"2","video.VideoId":["A value is required."],"video.UserId":["The UserId property is required."]}}

What am I misunderstanding here? As far as I know, WebAPI shouldn't care that a videoId wasn't provided.

1

1 Answers

5
votes

The difference is the RequiredAttribute is used solely for model validation where as the IsRequired property of the DataMemberAttribute is a hint to the serializer that says "upon serialization or deserialization, this property should always be present".

The DataMemberAttribute has no effect on the ModelStateDictionary.IsValid property and in the general MVC / Web Api model validation.

In your scenario, you need the RequiredAttribute (or any of the validation attribute in the System.ComponentModel.DataAnnotations namespace)

Edit:

Ideally, you should use different model, suited for your Api's endpoint and not your Entity Framework's model directly. Because Entity Framework code-first use the same attributes as the MVC / Web Api for validation, you can't mix the two if they don't translate one on one. In my opinion, you should create a separate class for the request in your controller. For example:

public class VideoModel
{
    public int? VideoId { get; set; }

    public int? UserId { get; set; }

    [Required]
    public string Title { get; set; }

}

// And your method
public HttpResponseMessage YourAction(VideoModel model)
{
    // Manipulate your model and map them to your Entity Framework's model
}

Note that the use of int?. If they are not required and left as an int, it will default to 0. Either you leave VideoModel as an int and treat 0 as a special value (but then, how will you differentiate a request that genuinely sent 0) or you use int?.HasValue to know if it was sent with the request.