在返回WebAPI控制器中的对象列表时,我一直在努力输出自定义根xml元素。
我的控制器方法看起来像这样:
public List<Product> Get()
{
return repository.GetProducts();
}
它呈现这样的xml输出:
<ArrayOfProduct>
<Product>
<Name>Product1</Name>
</Product>
<Product>
<Name>Product2</Name>
</Product>
</ArrayOfProduct>
我想把<ArrayOfProduct>
改成<Products>
,但还没有找到这样做的方法
我尝试过DataContract
和DataMember
属性的不同变体,但都没有成功。
有人知道是否有一种方法可以做我想要的事情,除了将我的List<Product>
对象包装到一个新类中并返回它之外?
我知道你不喜欢包装器的想法,但有一种解决方案在一定程度上使用了包装器,但也使用了非常容易使用的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>
请不要忘记查看列出的网站。
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; }
}
正如难以捉摸所说。。。。
[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")]
,它会列出它们而不分组。
我猜您使用的是NetDataContractSerializer
您可以在序列化程序的构造函数中指定根元素名称:
NetDataContractSerializer serializer = new NetDataContractSerializer("Products", "Your.Namespace");
看看差异重载:
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.netdatacontractserializer.aspx
我也遇到了同样的问题,进行了搜索,但找不到任何合适的解决方案,所以最终决定用"Products"替换字符串"ArrayOfProduct",它运行得很顺利。
我知道这样做不好,但很快。
您应该能够使用此处列出的Xml序列化属性
我已经有一段时间没有和他们一起工作了,但他们很快就学会了。
请检查一下。这里有一些关于如何以xml格式配置类输出的信息。
https://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute%28v=vs.110%29.aspx
在我看来,这与wep-api无关,而是与类的配置有关。
我已经做过很多次了,自定义xml序列化输出。在我的类定义中使用属性:
[XmlArray("Products")]
public List<Product> Products
{
get { return repository.GetProducts(); }
}
这应该会让你得到你想要的输出。。。