如何在XML序列化运行时更改XML元素的名称(ASP.Net WebApi)

时间:2017-02-23 17:24:57

标签: c# asp.net asp.net-web-api xml-serialization

我正在构建对WebAPI服务调用的响应。默认的XML Serializer主要适用于我。我需要生成的是这样的:

<fooCollection>
  <fooMember>
    <fooType1>
      ...bunch of properties for the fooMember
    </fooType1>
  </fooMember>
  <fooMember>
    <fooType2>
      ...bunch of properties for the fooMember
    </fooType2>
  </fooMember>
</fooCollection

我遇到的问题是<fooType>元素当前是我模型中的一个名为fooType的对象。响应中的元素名称需要具有不同的名称,具体取决于fooMember对象的type属性。这意味着使用[DataContract][DataMember]属性之类的内容为其命名而不是对象名称似乎无法正常工作,因为它们已设置一次而我无法找到如何更改在运行时。

我的模型代码如下所示:

  public partial class fooCollection {
    private fooCollectionMember[] memberField;

    [System.Xml.Serialization.XmlElementAttribute("fooMember")]
    public fooCollectionMember[] member { get; set;}
  }

  public partial class fooCollectionMember {
    private fooType fooTypeField;
    public fooType fooType { get; set }
  }

  public partial class fooType {
    private object fooProperty;
    // ... more properties
    public object fooProperty { get; set; }
    // ... more properties
  }

在运行时/序列化期间有没有办法可以设置我的元素名称对于<fooType>元素的含义?

或者,是否有一种方法可以重新排列我的模型,因此fooType不是包含其余属性的对象,而是fooMember对象的属性以及所有其他属性,但在序列化时,<fooType>元素被命名为该属性的值,并将其余属性封装在其中?

1 个答案:

答案 0 :(得分:0)

我的原始服务调用get方法是这样的:

    public FooCollection Get () {
      FooCollection foos = new FooCollection();
      // code to fill model
      return foos;
    }

我发现没有任何东西允许我在响应中获取基于FooCollection中的属性或对象的XML元素,并根据属性/对象的值更改XML响应中的元素名称。即,我不能拥有FooProperty属性,其XML响应中生成的元素对每个集合项具有不同的元素名称。换句话说,如果我使用return-a-model-object-and-let-the-serialization-happen-automatic方法,那么这个属性在整个XML文档中只能有一个元素名称。但是,我找到了一个解决方法,允许我更改元素名称,但我觉得合适。

而不是让我的Get()服务方法返回FooCollection类型的对象并在返回后自动序列化,而是返回HttpResponseMessage对象。通过这种方式,我可以手动序列化我的模型,然后根据需要对其进行操作,然后将其作为HttpResponseMessage返回。

所以现在我的get服务方法看起来更像是为了实现我的目标:

public HttpResponseMessage Get () {
  XmlSerializer xmlSerializer = new XmlSerializer(typeof(FooCollection));
  System.IO.StringWriter stringWriter = new System.IO.StringWriter();
  XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
  FooCollection foos = new FooCollection();
  // code to populate FooCollection model, assign namespaces, etc
  xmlSerializer.Serialize(stringWriter, foos, namespaces);
  // Now we can manipulate stringWriter value however is needed to replace the element names
  return new HttpResponseMessage() {
    Content = new StringContent(stringWriter.ToString(), Encoding.UTF8, "application/xml")
  };
}