Question

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.

Was it helpful?

Solution

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; }
    }

OTHER TIPS

public static class WebApiConfig
    {
//....
        public static void Register(HttpConfiguration config)
        {  config.Formatters.XmlFormatter.UseXmlSerializer = true;
        GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling =
        Newtonsoft.Json.PreserveReferencesHandling.Objects;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top