Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
332 views
in Technique[技术] by (71.8m points)

serialization - WCF and .NET 5.0: Issue with byte array deserialization

I'm trying to consume existing WCF services (basic binding) and I'm facing some issues related with the deserialization of the received message. Let me start by showing a snippet of the message:

<s:Body>
  <ObtemUtilizadoresResponse xmlns="http://xxx. pt/Mercados"><ObtemUtilizadoresResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
     <util>
       <Id>123</Id>
       <ver>AAAAAACL5j4=</ver>
       <im>-2</im>
       <n>User 123</n>
     </util>
   ....
</s:Body>

Initially, I've start by creating a new DTO for performing the deserialization which looks like this:

[DataContract(Namespace = "http://xxx.pt/Mercados", Name = "util")]
public class Utilizador {
    [field: DataMember(Name = "Id")]
    public int Id { get; set; }
    
    [field: DataMember(Name = "ver")]
    private byte[] Version { get; set; }
    
    [field: DataMember(Name = "n")]
    public string Nome { get; set; }
   
    [field: DataMember(Name = "im")]
    public int IdMercado { get; set; }
}

Even though the instance is created, it will only fill the Id and Version properties. If I remove the Version property, then the remaining properties are filled. In order to get all the properties filled, I had to move Version to a base class:

[DataContract(Namespace = "http://xxx. pt/Mercados", Name = "vb")]
public class Base {       
    [field: DataMember(Name = "ver")]
    private byte[] Version { get; set; }
}

[DataContract(Namespace = "http://xxx.pt/Mercados", Name = "util")]
public class Utilizador:Base {
... //removed Version property

Does anyone know why this is happening?

Thanks.

question from:https://stackoverflow.com/questions/65903958/wcf-and-net-5-0-issue-with-byte-array-deserialization

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

After some digging, it seems like there's an explanation for this behavior. When you use the DataContractSerializer, the default serialization order inside the type is alphabetical, and if you're using a class hierarchy, the order is top down. If there's a mismatch in the serialization order, the members will be initialized to their default values. That's why everything worked out fine when I introduced the base class (because the service uses a base class for the type being serialized).

So, if you want to flatten the hierarchy on the client side, you'll need to resort to the Order property of the DataMemberAttribute. You can apply the correct order position to each property (so that it mimics what's being serialized on the server) or you can "group" them by giving the same value to the properties that belong to the each level of the hierarchy (and rely on the the default alphabetical order for the properties that have the same order value - which, btw, is base on the Name property, if you're also setting it):

[DataContract(Namespace = "http://xxx.pt/Mercados", Name = "util")]
public class Utilizador {
    [field: DataMember(Name = "Id", Order = 1)]
    public int Id { get; set; }

    [field: DataMember(Name = "ver", Order = 1)]
    private byte[] Version { get; set; }

    [field: DataMember(Name = "n", Order = 2)]
    public string Nome { get; set; }

    [field: DataMember(Name = "im", Order = 2)]
    public int IdMercado { get; set; }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...