1

I cannot receive list in my WCF endpoint.

This is my XML file. I can't edit this structure

<wcf:Carro>
   <wcf:Fabricante>
      <wcf:Fabricante>
         <wcf:Id>
            <wcf:Id>0001</wcf:Id>
         </wcf:Gid>
      </wcf:Fabricante>
   <wcf:Acessorio>
      <wcf:Descrição>Test</wcf:Descrição>
   </wcf:Acessorio>
      <wcf:Acessorio>
      <wcf:Descrição>Test</wcf:Descrição>
   </wcf:Acessorio>
      <wcf:Acessorio>
      <wcf:Descrição>Test</wcf:Descrição>
   </wcf:Acessorio>
      <wcf:Acessorio>
      <wcf:Descrição>Test</wcf:Descrição>
   </wcf:Acessorio>
      <wcf:Acessorio>
      <wcf:Descrição>Test</wcf:Descrição>
   </wcf:Acessorio>
      <wcf:Acessorio>
      <wcf:Descrição>Test</wcf:Descrição>
   </wcf:Acessorio>
      <wcf:Acessorio>
      <wcf:Descrição>Test</wcf:Descrição>
   </wcf:Acessorio>
</wcf:Carro>

This is my class:

using System.Collections.Generic;
using System.Runtime.Serialization;
namespace WCFService
{
    [DataContract(Namespace = "http://mywcfservice.com/webservice")]
    public class Carro
    {
        [DataMember(Order = 1)]
        public Marca Marca { get; set; }

        [DataMember(Order = 2)]
        public Acessorio[] Acessorio { get; set; }
    }
}

Informations about Fabricante I'm receiving, but the list of "Acessorio" don't.

What am I doing wrong ?

Edit: I did some adjustments.

Note: If I include a new node wcf:Acessorio and inside this node I put others wcf:Acessorio then works. But I can't change XML structure.

  • Maybe this is useful: https://stackoverflow.com/a/47861221/578411 – rene Apr 22 '19 at 19:33
  • @rene about tag Fabricante, it was copy/paste error. I included xml namespace and still not working. Any other suggestion ? – Alexandre Bueno Apr 22 '19 at 19:51
  • An important information: If I add a new tag called and inside this tag I put others works. But I can't change the XML structure. – Alexandre Bueno Apr 22 '19 at 19:54
  • I doubt you can actually deserialize a list if it isn't in a container by itself, as your own testing showed . Worst case you have to do the reading of the xml yourself by using the Message instance: https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/using-the-message-class – rene Apr 22 '19 at 19:58
  • would you mind sharing the practical scenario you are using? – Abraham Qian Apr 23 '19 at 08:56
  • @AbrahamQian I need to create an endpoint to receive this XML structure. I can't change XML, I just need save this XML in my database. – Alexandre Bueno Apr 23 '19 at 11:32
  • @rene Not working yet – Alexandre Bueno Apr 23 '19 at 12:07

1 Answers1

1

You can't read that XML payload with the DataContract serializer.

First, switch your WCF service to use the XmlSerializer:

[ServiceContract]
[XmlSerializerFormat]
public class WcfService
{
    [OperationContract]
    public void TheOperation(Carro carro)
    {
        // do what you need to do
    }
}

Now use a datacontract that uses the XmlAttributes to control its serialization:

[XmlRoot(ElementName="Carro", Namespace="wcf")]
public class Carro
{
    [XmlElement]
    public Fabricante Fabricante { get; set; }

    [XmlElement]
    public List<Acessorio> Acessorio { get; set; }
}

To verify if this class works I have used the following test rig in LinqPad:

    var xml=@"<wcf:Carro xmlns:wcf=""wcf"">
      <wcf:Fabricante>
         <wcf:Id>0001</wcf:Id>
      </wcf:Fabricante>
   <wcf:Acessorio>
      <wcf:Descrição>Test</wcf:Descrição>
   </wcf:Acessorio>
      <wcf:Acessorio>
      <wcf:Descrição>Test</wcf:Descrição>
   </wcf:Acessorio>
      <wcf:Acessorio>
      <wcf:Descrição>Test</wcf:Descrição>
   </wcf:Acessorio>
      <wcf:Acessorio>
      <wcf:Descrição>Test</wcf:Descrição>
   </wcf:Acessorio>
      <wcf:Acessorio>
      <wcf:Descrição>Test</wcf:Descrição>
   </wcf:Acessorio>
      <wcf:Acessorio>
      <wcf:Descrição>Test</wcf:Descrição>
   </wcf:Acessorio>
      <wcf:Acessorio>
      <wcf:Descrição>Test</wcf:Descrição>
   </wcf:Acessorio>
</wcf:Carro>";

var obj = new Carro { 
    Fabricante = new Fabricante { Id ="0001"},
    Acessorio =  new List<Acessorio> { 
           new Acessorio{ Descrição = "1"}, 
           new Acessorio{ Descrição = "2"} } 
    };

var xs = new XmlSerializer(typeof(Carro));
using(var ms = new MemoryStream())
{
  using(var xw = XmlWriter.Create(ms, new XmlWriterSettings {Indent = true, OmitXmlDeclaration = true}))
   xs.Serialize(xw, obj);
  Encoding.UTF8.GetString(ms.ToArray()).Dump("serialized result");

  var o = (Carro) xs.Deserialize(XmlReader.Create(new StringReader(xml)));
  o.Dump("deserialized result");
}

Where the result of the serialization result is:

<Carro xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="wcf">
  <Fabricante>
    <Id>0001</Id>
  </Fabricante>
  <Acessorio>
    <Descrição>1</Descrição>
  </Acessorio>
  <Acessorio>
    <Descrição>2</Descrição>
  </Acessorio>
</Carro>

which matches our expected input.

rene
  • 41,474
  • 78
  • 114
  • 152