14

Mam problem z wyprowadzeniem niestandardowego elementu głównego xml podczas zwracania listy obiektów w moim kontrolerze WebAPI.Zmodyfikuj nazwę elementu tablicy XML w serializowanym obiekcie ASPAPI ASP.NET

Moja metoda kontroler wygląda mniej więcej tak:

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

który powoduje wyjście xml tak:

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

chciałbym zmienić <ArrayOfProduct> do <Products> ale nie znalazłem sposobu robiąc tak.

Próbowałem różnych odmian atrybutów DataContract i DataMember bezskutecznie.

Czy ktoś wie, czy istnieje sposób robienia tego, co chcę, bez owijania mojego obiektu List<Product> w nowej klasie i zwracania go zamiast tego?

+0

Tutaj jest podobny wątek - http://stackoverflow.com/a/11794647/2152334. Odpowiedź pod warunkiem, że można ją łatwo poprawić za pomocą ActionFilters, aby była bardziej ogólna i deklaratywna. – Yura

Odpowiedz

0

Chyba używasz NetDataContractSerializer
Można określić nazwę elementu głównego w konstruktorze serializer za:

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

Spójrz na tych zróżnicowanych przeciążeń:

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

+0

Dzięki, ale nie dokonuję ręcznego serializowania obiektu. Moja metoda działania zwraca mój obiekt do 'System.Web.Http.ApiController', więc nie widzę jak mogę sterować wyjściami z tego? – heidgert

0

I borykał się z tym samym problemem i szukał go, ale nie znalazł właściwego rozwiązania, więc w końcu zdecydował się na zamianę ciągu znaków "ArrayOfProduct" na "Produkty". wygładzanie gładkie.

Wiem, że jest to zły sposób, ale jest szybki.

0

Powinieneś być w stanie korzystać z języka XML attirbues serializacji jak nakreślono here

Jest już trochę czasu odkąd pracował z nimi, ale były szybkie i łatwe do nauczenia.

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

Zrobiłem to wiele razy, dostosowując wyjście serializacji xml. Używanie atrybutów w moich definicjach klas:

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

powinno Ci wyjście czego szukacie ...

+4

XmlArrayAttribute nie jest poprawna dla metod. –

+0

@PeterHedberg masz rację. edytowane w celu odzwierciedlenia metody składni właściwości. – jogi

1

wiem, że nie lubią idei otoki ale nie jest to rozwiązanie, które w pewnym stopniu wykorzystuje owijkę ale także używa atrybutów xml, które są bardzo łatwe w obsłudze. Moja odmowa zastosowania poniższego podejścia polega na użyciu starego serializera.

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

Teraz kontroler może po prostu wrócić produktów, takich jak:

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

teraz można określić serializatora w rozruchu tak:

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

wiem, że to nie jest najbardziej Idealny sposób na określenie serializera i utratę elastyczności i wygody EF i Linq. Albo przynajmniej trzeba interweniować, a nie tylko zwracać IEnumerable <>.

muszę dać kredytu na poniższej stronie, jak po raz pierwszy dowiedział się o tej drodze z witryny pod adresem: http://justthisguy.co.uk/outputting-custom-xml-net-web-api/

Spowoduje to w następujący 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> 

Proszę nie zapomnieć aby przejrzeć wymienioną witrynę.

1

jako nieuchwytny powiedział ....

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

Jeśli masz problemy, ponieważ jest to metoda, a następnie spróbuj przedefiniowania go jako własność, ponieważ bierze żadnych parametrów, a prawdopodobnie więcej sensu.

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

To będzie lista wszystkich Product elementy wewnątrz elementu elementu o nazwie „produkty”.

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

P.S. Aby zmienić nazwę znaczników pozycji Product, możesz użyć atrybutu [XmlArrayItem("Product")], aby to zrobić. Jeśli chcesz mieć listę płaską (nie zawijaj ich w "Produkty"), możesz użyć nazwy [XmlElement("Product")], która wyświetli je bez grupowania.

+1

Witam. Ten kod daje mi błąd "xmlarray nie jest poprawny w tym typie deklaracji". czy możesz zaproponować wyjście? –

Powiązane problemy