修改序列化ASP.NET WebAPI对象中的xml数组元素名称

时间:2012-07-22 10:21:33

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

在WebAPI控制器中返回对象列表时,我一直在努力输出自定义root xml元素。

我的控制器方法如下所示:

    public List<Product> Get()
    {
        return repository.GetProducts();
    }

,它呈现如下的xml输出:

<ArrayOfProduct>
  <Product>
    <Name>Product1</Name>
  </Product>
  <Product>
    <Name>Product2</Name>
  </Product>
</ArrayOfProduct>

我想将<ArrayOfProduct>更改为<Products>但尚未找到方法。

我尝试了DataContractDataMember属性的不同变体无济于事。

有没有人知道是否有办法做我想做的事情,而不是将我的List<Product>对象包装在一个新类中而是返回它?

8 个答案:

答案 0 :(得分:1)

class Program
{
    static void Main(string[] args)
    {
        HttpConfiguration config = new HttpConfiguration();

        DataContractSerializer productsSerializer = new DataContractSerializer(typeof(List<Product>), "Products", String.Empty);
        config.Formatters.XmlFormatter.SetSerializer(typeof(List<Product>), productsSerializer);

        config.Formatters.XmlFormatter.Indent = true;

        config.Formatters.XmlFormatter.WriteToStreamAsync(
            typeof(List<Product>),
            new List<Product> { new Product { Name = "Product1" }, new Product { Name = "Product2" } },
            Console.OpenStandardOutput(),
            null,
            null).Wait();

        Console.WriteLine();
    }
}

[DataContract(Namespace = "")]
public class Product
{
    [DataMember]
    public string Name { get; set; }
}

答案 1 :(得分:1)

我知道你不喜欢包装器的想法,但有一个解决方案有点使用包装器,但也使用非常容易使用的xml属性。我拒绝使用以下方法是使用旧的序列化程序。

public class Product
{
    [XmlAttribute( "id" )]
    public int Id
    {
        get;
        set;
    }
    [XmlAttribute( "name" )]
    public string Name
    {
        get;
        set;
    }
    [XmlAttribute( "quantity" )]
    public int Quantity
    {
        get;
        set;
    }
}
[XmlRoot( "Products" )]
public class Products
{
    [XmlAttribute( "nid" )]
    public int Id
    {
        get;
        set;
    }
    [XmlElement(ElementName = "Product")]
    public List<Product> AllProducts { get; set; }
}

现在您的控制器可以返回以下产品:

    public Products Get()
    {
        return new Products
        {
            AllProducts = new List<Product>
            {
                new Product {Id = 1, Name = "Product1", Quantity = 20},
                new Product {Id = 2, Name = "Product2", Quantity = 37},
                new Product {Id = 3, Name = "Product3", Quantity = 6},
                new Product {Id = 4, Name = "Product4", Quantity = 2},
                new Product {Id = 5, Name = "Product5", Quantity = 50},
            }
        };
    }

现在您可以在启动时指定序列化程序,如下所示:

    var productssXmlFormatter = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
    productssXmlFormatter.SetSerializer<Products>( new XmlSerializer( typeof( Products ) ) );

我知道这不是最理想的方式,因为必须指定序列化器并失去EF和Linq的灵活性和便利性。或者至少不得不干预而不仅仅是返回IEnumerable&lt;&gt;。

我必须从以下网站获得赞誉,因为我首先从网站上了解到这一点:http://justthisguy.co.uk/outputting-custom-xml-net-web-api/

这将产生以下xml:

<Products nid="0">
    <Product id="1" name="Product1" quantity="20"/>
    <Product id="2" name="Product2" quantity="37"/>
    <Product id="3" name="Product3" quantity="6"/>
    <Product id="4" name="Product4" quantity="2"/>
    <Product id="5" name="Product5" quantity="50"/>
 </Products>

请不要忘记查看列出的网站。

答案 2 :(得分:1)

难以捉摸的说......

[XmlArray("Products")]
public List<Product> Get()
{
    return repository.GetProducts();
}

如果您遇到问题,因为它是一种方法,那么请尝试将其重新定义为属性,因为它不需要参数,并且可能更有意义。

[XmlArray("Products")]
public List<Product> Products { 
  get {
    return repository.GetProducts();
  }
}

这将列出名为“Products”的元素元素中的所有Product项。

<Products>
  <Product>
    <Name>Product1</Name>
  </Product>
  <Product>
    <Name>Product2</Name>
  </Product>
</Products>

P.S。要重命名Product项标记,您可以使用[XmlArrayItem("Product")]属性执行此操作。如果你想要一个平面列表(不要将它们包装在“产品”中),你可以使用[XmlElement("Product")],然后列出它们而不对它们进行分组。

答案 3 :(得分:0)

我猜你正在使用NetDataContractSerializer
您可以在序列化程序的构造函数中指定根元素名称:

NetDataContractSerializer serializer = new NetDataContractSerializer("Products", "Your.Namespace");

看看不同的重载:

http://msdn.microsoft.com/en-us/library/system.runtime.serialization.netdatacontractserializer.aspx

答案 4 :(得分:0)

我遇到了同样的问题并进行了搜索,但未找到任何正确的解决方案,因此最终决定将“ArrayOfProduct”字符串替换为“Products”,并且工作顺利。

我知道这样做很糟糕,但速度很快。

答案 5 :(得分:0)

您应该能够使用概述为here

的Xml序列化attirbues

自从我与他们合作以来已经有一段时间了,但是他们很容易学习。

答案 6 :(得分:0)

我已多次这样做,自定义xml序列化输出。在我的类定义中使用属性:

[XmlArray("Products")]
public List<Product> Products
{
    get { return repository.GetProducts(); }
}

这应该可以获得您正在寻找的输出......

答案 7 :(得分:0)

请检查一下。有一些关于如何以xml格式配置类输出的信息。

https://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute%28v=vs.110%29.aspx

在我看来,它不是关于wep api而是关于类的配置。