14

Non riesco a ottenere l'output di un elemento xml radice personalizzato quando si restituisce un elenco di oggetti nel controller WebAPI.Modifica il nome dell'elemento dell'array xml nell'oggetto WebAPI serializzato di ASP.NET

Il mio metodo di controllo simile a questa:

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

che rende un output XML come questo:

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

vorrei cambiare <ArrayOfProduct> a <Products> ma non hanno trovato il modo di così facendo.

Ho provato diverse varianti degli attributi DataContract e DataMember inutilmente.

Qualcuno sa se c'è un modo per fare ciò che voglio, a meno di avvolgere il mio oggetto List<Product> in una nuova classe e restituirlo invece?

+0

qui è thread simile - http://stackoverflow.com/a/11794647/2152334. La risposta fornita può essere facilmente migliorata tramite ActionFilters per essere più generica e dichiarativa. – Yura

risposta

0

immagino che si sta utilizzando NetDataContractSerializer
È possibile specificare il nome dell'elemento radice nel costruttore del serializzatore:

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

Date un'occhiata ai differenti sovraccarichi:

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

+0

Grazie, ma non sto serializzando manualmente il mio oggetto. Il mio metodo di azione restituisce il mio oggetto al 'System.Web.Http.ApiController' quindi non vedo come posso controllare l'output da lì? – heidgert

0

I stava affrontando lo stesso problema e cercato ma non è riuscito a trovare alcuna soluzione adeguata, quindi alla fine ha deciso di sostituire la stringa "ArrayOfProduct" con "Prodotti" ed è ork liscio.

So che non è il modo migliore per farlo, ma è veloce.

0

Si dovrebbe essere in grado di utilizzare Xml attirbues serializzazione come delineato here

suo stato un po 'da quando ho lavorato con loro, ma erano veloce e facile da imparare.

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

Ho fatto questo molte volte, personalizzando l'output di serializzazione xml. Utilizzando gli attributi nelle mie definizioni di classe:

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

questo dovrebbe farti l'output che state cercando ...

+4

XmlArrayAttribute non è valido sui metodi. –

+0

@PeterHedberg hai ragione. modificato per riflettere la sintassi della proprietà non metodo. – jogi

1

so che non siete appassionati l'idea involucro ma c'è una soluzione che utilizza un po 'un wrapper ma usa anche gli attributi xml che sono molto facili da usare. Il mio rifiuto di utilizzare il seguente approccio è l'uso del vecchio serializzatore.

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

Ora il controller può semplicemente tornare Prodotti come:

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

ora è possibile specificare il serializzatore in fase di start-up in questo modo:

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

So che non è il più modo ideale per dover specificare il serializzatore e perdere la flessibilità e la convenienza di EF e Linq. O almeno dover intervenire invece di restituire IEnumerable <>.

devo dare credito al seguente sito come ho imparato in questo modo dal sito all'indirizzo: http://justthisguy.co.uk/outputting-custom-xml-net-web-api/

Ciò comporterà il seguente codice 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> 

non dimenticate per guardare il sito elencato.

1

quanto sfuggente detto ....

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

Se si hanno problemi, perché è un metodo, quindi provare ridefinendo come una proprietà dal momento che non ha parametri, e probabilmente ha più senso.

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

che elencherà tutti i Product elementi all'interno di un elemento elemento denominato 'Prodotti'.

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

P.S. Per rinominare i tag articolo Product è possibile utilizzare l'attributo [XmlArrayItem("Product")] per fare ciò. Se si desidera avere un elenco semplice (non avvolgerli in "Prodotti"), è possibile utilizzare lo [XmlElement("Product")] e questo li elencherà senza raggrupparli.

+1

Ciao. Questo codice mi dà un errore "il xmlarray non è valido su questo tipo di dichiarazione". puoi suggerire una via d'uscita? –

Problemi correlati