I am writing a simple API using .Net's Web API. I have defined the following Model:
public class VehicleUpdate
{
[Required(ErrorMessage = "DealerID Required")]
public int DealerID { get; set; }
[Required(ErrorMessage = "VIN Required")]
[StringLength(17, ErrorMessage = "VIN Must be 17 characters", MinimumLength = 17)]
public string VIN { get; set; }
[StringLength(8000, ErrorMessage = "Comments must be less than 8,000 characters")]
public string Comments { get; set; }
public double Retail { get; set; }
}
I tried to test it by doing an HTTP Post with the following XML
<VehicleUpdate>
<DealerID>30</DealerID>
<VIN>1FMRU17L0WLA62356</VIN>
<Comments>This is a test.</Comments>
<Retail>1000</Retail>
</VehicleUpdate>
When I do this, I get the following SerializationException:
System.Runtime.Serialization.SerializationException: Error in line 1 position 16. Expecting element 'VehicleUpdate' from namespace 'http://schemas.datacontract.org/2004/07/API.Models'.. Encountered 'Element' with name 'VehicleUpdate', namespace ''. at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator xmlReader, Boolean verifyObjectName, DataContractResolver dataContractResolver) at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver) at System.Runtime.Serialization.DataContractSerializer.ReadObject(XmlReader reader) at System.Net.Http.Formatting.XmlMediaTypeFormatter.<>c_DisplayClass3.b_2()
Can someone please tell me what I am doing wrong? I thought this would be a valid XML message.
Two things:
AS the error says, DataContractSerializer
expects the XML to provide a proper namespace, and your XML doesn't have it.
You can either pass the namespace:
<VehicleUpdate xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/API.Models">
// properties
</VehicleUpdate>
Or switch to XmlSerializer
in your Web API configuration:
config.Formatters.XmlFormatter.UseXmlSerializer = true;
Then you can pass the exact XML you are passing now.
You might run into another issue, when using [Required]
on non nullable type i.e. int
. This is a known problem since int
will be always 0 instead of null if not passsed. In that case you might have to change your model to have excplicit DataContract
definition:
[DataContract]
public class VehicleUpdate
{
[DataMember(IsRequired = true)]
[Required(ErrorMessage = "DealerID Required")]
public int DealerID { get; set; }
[DataMember]
[Required(ErrorMessage = "VIN Required")]
[StringLength(17, ErrorMessage = "VIN Must be 17 characters", MinimumLength = 17)]
public string VIN { get; set; }
[DataMember]
[StringLength(8000, ErrorMessage = "Comments must be less than 8,000 characters")]
public string Comments { get; set; }
[DataMember]
public double Retail { get; set; }
}