【问题标题】:WCF not deserializing value types. Mysterious behaviourWCF 不反序列化值类型。神秘行为
【发布时间】:2013-03-06 09:10:50
【问题描述】:

服务代码:

[ServiceContract]
    public interface IServices
    {
        [OperationContract]
        [XmlSerializerFormat]
        GetProductsResponse Getproducts(GetProductsRequest productsrequest);

    [OperationContract]
    SaveProductsResponse SaveProducts1(SaveProductsRequest1 productsrequest);
} 


public class GetProductsRequest
{
    [XMLElement]
    public string id;

    [XMLElement,typeof(Person)]
    public Person[] Persons;
}

[DataContract]
public class SaveProductsRequest1
{
    [DataMember]
    public List<Person> Persons;
}


[DataContract]
public class Person
{
    [DataMember]
    public int Id;

    [DataMember]
    public string Name;

    [DataMember]
    public Sex Sex;
}

[DataContract]
public enum Sex
{
    [EnumMember]
    Male,
    [EnumMember]
    Female
}

客户:

ServicesClient client = new ServicesClient();
SaveProductsRequest1 req = new SaveProductsRequest1();
req.Persons = new List<Person> { new Person { Id = 10, Name = "Al", Sex = Sex.Female} }.ToArray();

client.SaveProducts1(req);

我能够在服务端获取值“Al”(字符串)。但是值 10 和 Male(值类型)在服务端被重置为默认值(0 和 Male)。

只有当我将 XMLElement 用于任何数组属性和一个额外的字符串属性时,我在服务合同(在本例中为 GetProducts)和我的 GetProducts 类中为我的任何一种方法设置了 XmlSerializerFormat 时才会发生这种情况。

WCF 运行时有问题吗?

【问题讨论】:

  • 请包含 Person 类
  • 我们能看看Person是如何声明的吗?
  • 数据合约长什么样?
  • 嗯...您的Person 课程无法完成。一定是缺少Sex数据成员
  • @Al.Net Sex 在哪里?我担心的是,我们会追逐一个明显不同的课程版本中不存在的问题

标签: c# .net wcf c#-4.0


【解决方案1】:

我已经使用您的服务器端代码设置了一个测试 WCF 服务,并使用您的示例客户端代码再次设置了一个测试客户端,它工作正常:

如您所见,1 Person 被完整传输,所有 3 个值都完好无损。如果您最后发生了一些不同的事情,它可能与您的配置文件中的配置选项有关,但从根本上说:代码有效。我正在使用 .NET 4.5 进行测试

【讨论】:

  • 我要看看你们的服务合同吗?因为我的代码也运行良好。只有当我的方法之一具有 [XMLSerialzeFormat] 属性(在我的情况下,它是 Getproducts)时,才会出现问题。请张贴您的服务合同及其运营合同及其班级成员
  • @Al.Net 我有你问题中的代码;我从问题中改变的只是为其他 3 种类型添加虚拟存根:[DataContract] public class SaveProductsResponse { }[DataContract] public class GetProductsRequest { }[DataContract] public class GetProductsResponse { }。有关信息,我还在 2 个“产品”相关类型上测试了没有 [DataContract] 的情况 - 它仍然可以正常工作。
  • 让我也试试新样本 Marc
  • 让我发布我的 GetProductsRequest 。您可以尝试在您的示例中使用我的 GetProductsRequest 吗?因为我在使用该类时遇到问题
  • 如果我从 GetProductRequest 中删除属性 Persons 的 XMLElement 属性并将其设置为 XMLArrayItem 属性,那么一切都很好。我可以知道为什么这个 XMLElement 属性会导致值类型反序列化问题吗?
【解决方案2】:

您的服务合同是否用ServiceContract 属性修饰:

[ServiceContract]
public interface IServices
{
    // ...
}

我只是希望你在这里没有向我们展示不同的东西。

【讨论】:

  • 是的,我有 ServiceContract。现在编辑它。谢谢
  • @Al.Net 你可以看到,不过,如果省略这些细节,我们很难找到正确的东西;)
【解决方案3】:

只有当我在服务合同中的任何一种方法(在本例中为 GetProducts)都有 XmlSerializerFormat 时才会发生这种情况。

在这种情况下,WCF 使用XmlSerializer 来序列化数据。因此[DataContract][DataMember] 都不适用。如果你真的必须使用XmlSerializer,并且需要进一步控制XML序列化,你需要使用它的特定属性,例如[XmlElement][XmlAttrribute][XmlIgnore]。明确的做法是一种很好的做法,以避免因无意重命名字段或属性而导致难以发现的问题:

public class Person
{
    [XmlElement("Id")]
    public int Id { get; set; }

    [XmlElement("Name")]
    public string Name { get; set; }

    [XmlIgnore] // don't tell the stranger
    public Sex Sex { get; set; }
}

还要注意[Serializable] 属性与 XML 序列化和数据协定序列化无关。它与二进制序列化有关。

【讨论】:

  • 我有 2 个问题。我想要 getproducts 中的 xmlserialization(工作正常)但 saveproducts 中的 datacontractserialization。我怎样才能做到这一点?那么我不应该在同一个服务合同的操作合同级别同时使用两种序列化类型吗?
  • 不需要用属性标记它们,也不需要使用属性。假定为“元素”,并且字段工作正常 - 这是完全支持。
  • 使用 XML 序列化程序和数据协定序列化程序的属性来装饰您的成员。
  • 我已经用 [Serializable] 和 [DataContract] 进行了装饰。但是值类型仍然没有被反序列化。为什么我要使用两个序列化类型是 GetProducts 是旧代码并使用 xmlattribute。但是 saveproduct 是新要求,应该使用 datacontractserialization
  • @MarcGravell 嗯,需要再来一杯咖啡……现在回答这个问题还为时过早 :-) 是的,你是对的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多