1

I am writing a Web API with ASP.NET Web API, and make use of the following View Model. I seem to be having a problem with the data binding when there are two validation attributes on a particular property (i.e. [Required] and [StringLength(10)]).

When posting a JSON value from a client to a controller action of the form:

// POST api/list

public void Post([FromBody] TaskViewModel taskVM)

I observe the following:

  • If I remove one of the multiple attributes everything is bound OK;
  • If I leave in the multiple attributes, the client recieves a 500 internal server error and the body of the Post method is never reached.

Any ideas why this happens? Cheers

public class TaskViewModel
{

    //Default Constructor
    public TaskViewModel() { }


    public static TaskViewModel MakeTaskViewModel(Task task) 
    {
        return new TaskViewModel(task);
    }

    //Constructor
    private TaskViewModel(Task task)
    {
        this.TaskId = task.TaskID;
        this.Description = task.Description;
        this.StartDate = task.StartDate;
        this.Status = task.Status;
        this.ListID = task.ListID;
    }

    public Guid TaskId { get; set; }

    [Required]
    [StringLength(10)]
    public string Description { get; set; }

    [Required]
    [DataType(DataType.DateTime)]
    public System.DateTime StartDate { get; set; }

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

    public System.Guid ListID { get; set; }       
}

1 Answer 1

4

You need to inspect what is inside in the 500 internal server

  • make sure that you turn customerror off in your web.config
  • If you selfhost web.API you need to set GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
  • use your browser development console's network tab (in IE, Chrome you can get the console with F12) or if you are using FireFox then use FireBug or a thrid party tool like Fiddler.

Then you can see what went wrong on the server and go further to solve your problem.

In your case this is in the response:

"Message":"An error has occurred.","ExceptionMessage":"Property 'StartDate' on type 'MvcApplication3.Controllers.TaskViewModel' 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)].","ExceptionType":"System.InvalidOperationException"

So your problem is not that you have two attributes but that you've marked your properties with [Required] to solve this the exception tells you what to do.

You need to add [DataMember(IsRequired=true)] to your required properties where the property type is a value type (e.g int, datatime, etc.):

So change your TaskViewModel to:

[DataContract]
public class TaskViewModel
{

    //Default Constructor
    public TaskViewModel() { }

    [DataMember]
    public Guid TaskId { get; set; }

    [Required]
    [DataMember]
    [StringLength(10)]
    public string Description { get; set; }

    [Required]
    [DataMember(IsRequired = true)]
    [DataType(DataType.DateTime)]
    public System.DateTime StartDate { get; set; }

    [Required]
    [DataMember]
    public string Status { get; set; }

    [DataMember]
    public System.Guid ListID { get; set; }
}

Some side notes:

  • You need to reference the System.Runtime.Serialization dll in order to use the DataMemberAttribute
  • You need to mark your class with [DataContract] and you need to mark all of its properties with [DataMember] not just the required ones.
Sign up to request clarification or add additional context in comments.

1 Comment

Great, that's fixed problem. Much Appreciated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.