14

在我的 WebAPI 控制器中返回对象列表时,我一直在努力输出自定义根 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>,而不是将我的对象包装在一个新类中并返回它?

4

8 回答 8

2

我知道您不喜欢包装器的想法,但是有一个解决方案在某种程度上使用了包装器,但也使用了非常易于使用的 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<>。

当我第一次从以下站点了解到这种方式时,我必须感谢以下站点: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>

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

于 2015-03-14T19:36:25.257 回答
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; }
}
于 2012-11-15T21:25:33.957 回答
1

就像难以捉摸的那样......

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

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

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

这将列出Product名为“产品”的元素元素内的所有项目。

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

PS 要重命名Product项目标签,您可以使用该[XmlArrayItem("Product")]属性来执行此操作。如果您想要一个平面列表(不要将它们包装在“产品”中),您可以使用[XmlElement("Product")]and 将它们列出而不分组。

于 2015-04-20T01:30:40.757 回答
0

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

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

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

于 2015-04-06T23:43:39.580 回答
0

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

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

看看不同的重载:

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

于 2012-07-27T15:15:29.787 回答
0

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

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

这应该会给你你正在寻找的输出......

于 2012-11-16T15:46:01.483 回答
0

您应该能够使用此处概述的 Xml 序列化属性

自从我和他们一起工作已经有一段时间了,但他们学习起来又快又容易。

于 2012-10-16T20:52:46.070 回答
0

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

我知道这样做是不好的,但它很快。

于 2012-08-29T05:59:57.900 回答