locked
Web API, problems with XML and POST RRS feed

  • Question

  • User669267014 posted

    I think that I have found a bug with webapi. Seen a couple of people having problems with this and there seems to be a pattern.

    A simple service to initiate a print of invoices. Taking three parameters which are sent in as XML in a post request.

    public HttpResponseMessage Post([FromBody]PrintRequest value)
    {
    var response = Request.CreateResponse<PrintRequest>(HttpStatusCode.Accepted, value);
    return response;
    }
    public class PrintRequest
    {
    public string A { get; set; } 
    public string B { get; set; }
    public string C { get; set; } 
    }
    

    When posting the XML to the REST service the order of the parameters decides if they will be parsed or not. The alphabetical order of the parameters that is.

    <PrintRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/InvoiceService.Models">
    <a>A</a>
    <b>B</b> 
    <c>C</c> 
    </PrintRequest>

    With the order as described above all parameters are initiated.

    If the order is B, A, C only B and C will be initiated. Same result with the order B, C, A
    If the order is C, A, B or C, B, A only C will be initiated.

    From the tests I have performed my conclusion is that there is a bug in MVC4 Web API which puts a hard requirement on incoming parameters. Making all parameters that are out of order, later in the xml, fail to be parsed and initiated.

    Is there any solutions to this? A patch coming soon perhaps?

    Since this force the calling client to know of these limitations in the web api it kind of breaks web api for use with external parties. And we would prefer to have the option to use it where REST services are to prefer over SOAP ones.

    Friday, January 11, 2013 8:09 AM

All replies

  • User144126647 posted

    Input XML  should be 

    <PrintRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ExceptionTest.NewFolder1">

    <A>sample string 1</A>

    <B>sample string 2</B>
    <C>sample string 3</C>
    </PrintRequest>

    Why you are using small letters for the properties. If you change the XML it will work fine. XML Node should match with the property name.

    NOTE: There is no problem with ASP.Net Web API.

    <PrintRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ExceptionTest.NewFolder1">

    <A>a</A>

    <B>b</B>

    <C>c</C>
    </PrintRequest>

    Friday, February 8, 2013 2:02 PM
  • User669267014 posted

    I am sorry but you have misinterpreted the problem. The problem is not that you can't get all the parameters populated. But rather that they are only all populated if they are sent in the XML in sorted order.

    So if you send them in with A, B ,C as the order then all will go well. But if you send them in with C, A, B then only C will be parsed. This have been tried and tested now at three different companies all with the same result. 

    This is still an open issue and we would call it a substantial bug. 

    Regards

    Roine

    Friday, February 8, 2013 3:51 PM
  • User144126647 posted

    Default it will use Data Contract searilization one option will be use xml searilization then any order is working fine. 

    Add this in global.asax

     var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;

    xml.UseXmlSerializer = true;

    <PrintRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <C>sample string 3</C>

    <B>sample string 2</B>

    <A>sample string 1</A>
    </PrintRequest>

    if you want to use datacontract searilization you can mention the order you want insted of alphabetical.

    [DataContract]
    public class PrintRequest
    {
     [DataMember(Order=1)]
    public string A { get; set; } 
     [DataMember(Order=2)]
    public string B { get; set; }
     [DataMember(Order=3)]
    public string C { get; set; } 
    }


    Friday, February 8, 2013 4:42 PM
  • User669267014 posted

    But it is a hard coded order then? Since XML doesn't have an order and neither does a class definition. It have accessible entities that can be specified in any order the caller likes. And since the caller are external parties we are not in control of that. Which means that if we use web api for services we get support issues. Which we do not get if we use any other method I have come across so far.

    <Entity>
    <A/>
    <B/>
    <C/>
    </Entity>

    is equal to

    <Entity>
    <C/>
    <B/>
    <A/>
    </Entity>

    The meaning of the XML is the same and both validate the schema definition.
    Which means that if I put them in a different order hard coded it will not fix the issue. Only move the allowed order of the parameters. And XML serialization should not be bound by the order of which the callers puts his (or her) parameters. 

    Friday, February 8, 2013 6:22 PM
  • User144126647 posted

    Hi Roine,

    Did you tried the xml Serilization. I tried and tested working fine.

    Both these xml's are parsing. There is no order restriction.

    To using xmlsearialization all you need to do is adding these two lines in global.asax

    
    
    var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
    
    xml.UseXmlSerializer = true;

    Let me know what is the challenge, if you use xmlsearilization.

    Friday, February 8, 2013 10:32 PM
  • User-1481289139 posted

    I've just noticed the same issue. Did you resolve this problem? 

    While developing my first RESTful service I've the following test class.

     public class Order
        {
            public Order()
            {
                Lines = new List<OrderLine>();
            }
    
            public string CustomerName{get;set;}
            public string TelephoneNo{get;set;}
            public string Email{get;set;}
            public string MobileNo { get; set; }
            public string Address1 { get; set; }
            public string Address2 { get; set; }
            public string Address3 { get; set; }
            public string City { get; set; }
            public string County { get; set; }
            public string PostCode { get; set; }
            public string CountryCode { get; set; }
            public string SpecialMessage { get; set; }
            public string DelInstructions { get; set; }
            public string WebReference { get; set; }
    
            public IEnumerable<OrderLine> Lines { get; set; }
        }

      

    if I issue a POST with the following body (obvioulsy with correct xmlns details), an Order object is received by my Post method but only the Email element is populated with a value.

     

    <Order xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/...etc..">
      <Email>andrew@andrew.com</Email>
      <Address2>address line test</Address2>
      <CustomerName>andrew</CustomerName>
    </Order>
    

     

    If I re-sequence the above so that Email is after <CustomerName>, my Post method receives an Order object with AdressLine2, CustomerName and Email values simply because they've been received in alphabetical order.

    I also tries Dhanekula solution, but this simply caused an error in the API.  I've removed the Json formatter and set the Content-Type in the header to 'application/xml', so it can't use anything else apart from XML formatter.

    Andrew


     

     

     

    Thursday, July 11, 2013 11:16 AM
  • User534715995 posted

    The problem with using object serializers to create your "on-the-wire" formats is that they assume they are being used at both ends of the wire.  If you use DataContractSerializer to deserialize your XML then you have to play by its rules.  I'm assuming it sorts the properties in alphabetically order for performance reasons on deserialization.

     

    Thursday, July 11, 2013 5:40 PM
  • User1718106121 posted

    Roine,

    My results are exactly the same as yours and I would agree this is a substantial bug!

    Best regards,

    Darren

    I am sorry but you have misinterpreted the problem. The problem is not that you can't get all the parameters populated. But rather that they are only all populated if they are sent in the XML in sorted order.

    So if you send them in with A, B ,C as the order then all will go well. But if you send them in with C, A, B then only C will be parsed. This have been tried and tested now at three different companies all with the same result. 

    This is still an open issue and we would call it a substantial bug. 

    Regards

    Roine

    Wednesday, October 23, 2013 2:39 AM
  • User-689700299 posted

    I have the same issue with a new project and adding:

    var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
    xml.UseXmlSerializer = true;

    Means the pipeline parser that was working (if passed in alphabetic order) now returns a lovely null for my "frombody" object :/ 

    Thursday, September 8, 2016 10:16 AM