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

これで、コントローラーは次のような Products を返すことができます。

    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 に答える
0

私はこれを何度も行い、xml シリアライゼーション出力をカスタマイズしました。クラス定義で属性を使用する:

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

これにより、求めている出力が得られるはずです...

于 2012-11-16T15:46:01.483 に答える
0

ここで概説されているように、Xml シリアル化 attirbues を使用できる必要があります。

彼らと一緒に仕事をしてからしばらく経ちましたが、彼らは素早く簡単に習得できました。

于 2012-10-16T20:52:46.070 に答える
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

私は同じ問題に直面していて検索しましたが、適切な解決策が見つからなかったため、最終的に文字列「ArrayOfProduct」を「Products」に置き換えることにしました。スムーズに動作しています。

これを行うのが悪い方法であることは知っていますが、迅速です。

于 2012-08-29T05:59:57.900 に答える