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; }
}
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.
来源:https://stackoverflow.com/questions/14499244/problems-with-model-binding-and-validation-attributes-with-asp-net-web-api