XML 序列化在 Web API 中无法按预期工作 ASP.NET

本文关键字:工作 NET ASP 序列化 Web API XML | 更新日期: 2023-09-27 18:31:02

我们有一个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 客户端传递给 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>

在开始时放置偏移量和限制会以某种方式启用序列化。问题是我不能要求客户端按特定顺序构建请求。

有人可以让我知道这里到底发生了什么吗?

更新:

经过进一步分析,我开始知道数据成员的顺序会影响序列化,但我仍然认为我已经相应地对我的成员进行了排序,并为偏移量和极限值提供了最大顺序,以便它始终低于其他参数。 但它仍然为空

XML 序列化在 Web API 中无法按预期工作 ASP.NET

DataContractSerializer需要遇到元素的顺序如下所述: 数据成员顺序:

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

  • 如果数据协定类型是继承层次结构的一部分,则其基类型的数据成员始终排在顺序中的第一个。

  • 接下来依次是当前类型的数据成员,这些成员没有 DataMemberAttribute 属性集的 Order 属性(按字母顺序排列)。

  • 接下来是设置了 DataMemberAttribute 属性的 Order 属性的任何数据成员。它们首先按 Order 属性的值排序,如果某个 Order 值有多个成员,则按字母顺序排序。订单值可能会被跳过。

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

即基类数据成员(即 offsetlimitCriteria) 必须在派生类数据成员之前出现。

因此,以下是解决此规则的一些可能性:

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

  2. 使用数据协定代理项将派生类转换为平面代理项以进行序列化。

  3. 请与客户端联系并获取其服务模型元数据。 这将指定字段的顺序,并允许自动生成 c# 类。

  4. 考虑切换到 XMLSerializer。 文档在这里。