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

问题描述:

在我的WebAPI控制器中返回对象列表时,我一直在努力输出自定义根元素xml元素。在序列化的ASP.NET 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>对象包装到一个新类中,然后返回它?

+0

这里是类似的线程 - http://stackoverflow.com/a/11794647/2152334。提供的答案可以通过ActionFilters轻松改进,使其更具通用性和声明性。 – Yura 2015-03-31 15:32:52

我猜你正在使用NetDataContractSerializer
您可以在串行器的构造函数中指定的根元素名称:

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

看看该型动物重载:

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

+0

谢谢,但我不是手动序列化我的对象。我的动作方法返回我的对象​​到'System.Web.Http.ApiController',所以我不明白我可以如何控制从那里的输出? – heidgert 2012-08-03 09:41:10

我面临着同样的问题和搜索,但找不到任何适当的解决方案,所以最终决定用“产品”替换字符串“ArrayOfProduct”,它是w分工平稳。

我知道这是不好的方法来做到这一点,但它很快。

您应该能够使用XML序列化attirbues所概述here

它已经有一段时间,因为我已经与他们合作,但他们快速,简单易学。

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; } 
} 

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

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

这应该得到你正在寻找我知道你不喜欢包装的想法,但没有多少有些使用的包装解决方案的输出...

+4

XmlArrayAttribute在方法上无效。 – 2013-03-02 10:43:50

+0

@PeterHedberg你是对的。编辑以反映属性语法而非方法。 – jogi 2018-02-05 18:24:11

还使用了非常容易处理的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> 

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

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

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

在我看来,它不是关于WEP API,但类的配置。

难以捉摸说....

[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")],这将列出它们而不分组。

+1

嗨。此代码给我一个错误“xmlarray在这种声明类型上无效”。你能提出一条出路吗? – 2016-10-16 16:26:24