在ASP.NET Web Api中,Xml序列化无法正常工作

时间:2014-11-20 07:15:40

标签: c# asp.net xml serialization

我们有一个Web API,它为所有模型使用基类。以下是结构

基础抽象类

[DataContract(Namespace = "")]
public abstract class Criteria
{
    protected Criteria()
    {
        Offset = 0;
        Limit = 250;
    }
    [DataMember(Name = "offset", Order = 97, EmitDefaultValue = false)]
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
    public int? Offset { get; set; }

    [DataMember(Name = "limit", Order = 98, EmitDefaultValue = false)]
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
    public int? Limit { get; set; }
}

这实现了基本抽象类

[DataContract(Name = "insightCriteria", Namespace = "")]
public class InsightCriteria : Criteria
{
    [DataMember(Name = "geography", Order = 95, EmitDefaultValue = false)]
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
    [JsonConverter(typeof(StringEnumConverter))]
    public InsightGeography Geography { get; set; }
}

进一步实现上述课程的实际模型

[DataContract(Name = "jobReportCriteria", Namespace = "")]
public class JobReportCriteria : InsightCriteria
{
    [DataMember(Name = "groupBy", Order = 1, EmitDefaultValue = false)]
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
    [JsonConverter(typeof(StringEnumConverter))]
    public JobReportGroupings GroupBy { get; set; }

    [DataMember(Name = "timePeriod", Order = 2, EmitDefaultValue = false)]
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
    public TimePeriod TimePeriod { get; set; }

    [DataMember(Name = "queryString", Order = 3, EmitDefaultValue = false)]
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
    public string QueryString { get; set; }

    [DataMember(Name = "includeTotalClassifiedPostings", Order = 4, EmitDefaultValue = false)]
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
    public bool IncludeTotalClassifiedPostings { get; set; }

    [DataMember(Name = "includeTotalUnclassifiedPostings", Order = 5, EmitDefaultValue = false)]
    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
    public bool IncludeTotalUnclassifiedPostings { get; set; }
}

问题

现在问题是当使用json序列化时一切正常我在抽象类中接收偏移和限制的值。但是在使用XML序列化时,偏移和限制不会被填充。

以下是我通过Rest Client传递给api的请求

<jobReportCriteria>
  <groupBy>State</groupBy>
  <timePeriod>
    <from>2014-02-06T00:00:00</from>
    <to>2014-05-06T00:00:00</to>
  </timePeriod>
  <queryString>[nationwide]: &quot; nationwide &quot;</queryString>
  <includeTotalClassifiedPostings>true</includeTotalClassifiedPostings>
  <includeTotalUnclassifiedPostings>true</includeTotalUnclassifiedPostings>
  <includeLastDataDate>true</includeLastDataDate>
  <offset>0</offset>
  <limit>25</limit>
</jobReportCriteria>

奇怪的行为

如果我更改了元素的顺序,则会填充偏移量和限制。以下是正确序列化的请求

<jobReportCriteria>
  <offset>0</offset>
  <limit>25</limit>
  <groupBy>State</groupBy>
  <timePeriod>
    <from>2014-02-06T00:00:00</from>
    <to>2014-05-06T00:00:00</to>
  </timePeriod>
  <queryString>[nationwide]: &quot; nationwide &quot;</queryString>
  <includeTotalClassifiedPostings>true</includeTotalClassifiedPostings>
  <includeTotalUnclassifiedPostings>true</includeTotalUnclassifiedPostings>
  <includeLastDataDate>true</includeLastDataDate>
</jobReportCriteria>

在开始时设置偏移和限制可以启用序列化。问题是我无法要求客户按特定顺序构建请求。

有人能告诉我这里到底发生了什么吗?

更新

在进一步的分析中,我发现数据成员的顺序会影响序列化,但我仍然认为我已经相应地订购了我的成员,并给出了最大订单的偏移和限制值,因此它总是低于其他参数。但它仍然是空的

1 个答案:

答案 0 :(得分:0)

此处列出了DataContractSerializer要求遇到元素的顺序:Data Member Order

  

数据排序的基本规则包括:

     
      
  • 如果数据协定类型是继承层次结构的一部分,则其基本类型的数据成员始终位于订单中。

  •   
  • 接下来依次是当前类型的数据成员,它们没有按字母顺序设置DataMemberAttribute属性的Order属性。

  •   
  • 接下来是具有DataMemberAttribute属性集的Order属性的任何数据成员。它们首先按Order属性的值排序,然后按字母顺序排序,如果某个Order值有多个成员。可以跳过订单值。

  •   
     

通过调用CompareOrdinal方法建立字母顺序。

即,基类数据成员(即offset的{​​{1}}和limit)必须在派生类数据成员之前出现。

所以,这里有一些解决这条规则的可能性:

  1. 修改您的班级设计并展平您的班级层次结构。显然不理想,但您可以通过使用由平面类实现的接口层次结构替换类层次结构来实现。

  2. 使用data contract surrogate将派生类转换为平面代理代理以进行序列化。

  3. 与您的客户联系并获取他们的servicemodel metadata。这将指定字段的顺序,并允许c#类为automatically generated

  4. 考虑switching to XMLSerializer。文档here