14

He estado luchando con la salida de un elemento raíz xml personalizado al devolver una lista de objetos en mi controlador WebAPI.Modificar el nombre del elemento de la matriz xml en el objeto serializado ASP.NET WebAPI

Mi método controlador es como la siguiente:

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

que hace una salida XML como esto:

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

me gustaría cambiar a <ArrayOfProduct><Products> pero no han encontrado una manera de haciéndolo.

He intentado diferentes variaciones de los atributos DataContract y DataMember en vano.

¿Alguien sabe si hay una manera de hacer lo que quiero, sin envolver mi objeto List<Product> en una nueva clase y devolverlo en su lugar?

+0

aquí es un hilo similar - http://stackoverflow.com/a/11794647/2152334. Respuesta siempre que pueda mejorarse fácilmente a través de ActionFilters para ser más genérico y declarativo. – Yura

Respuesta

0

supongo que está utilizando NetDataContractSerializer
puede especificar el nombre del elemento raíz en el constructor del serializador:

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

Tome un vistazo a las sobrecargas diferentes:

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

+0

Gracias, pero no estoy serializando manualmente mi objeto. Mi método de acción devuelve mi objeto al 'System.Web.Http.ApiController', así que no veo cómo puedo controlar el resultado desde allí. – heidgert

0

I estaba enfrentando el mismo problema y buscó, pero no pudo encontrar ninguna solución adecuada, así que finalmente decidió reemplazar la cadena "ArrayOfProduct" por "Productos" y es w orking sin problemas.

Sé que es una mala forma de hacerlo, pero es rápido.

0

Usted debe ser capaz de utilizar attirbues serialización XML como se indica here

Ha sido un tiempo desde que he trabajado con ellos, pero eran rápido y fácil de aprender.

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

He hecho esto muchas veces, personalizando la salida de serialización xml. El uso de atributos en mis definiciones de clases:

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

esto debe conseguir que la salida que está buscando ...

+4

XmlArrayAttribute no es válido en los métodos. –

+0

@PeterHedberg estás en lo correcto. editado para reflejar la sintaxis de la propiedad, no el método. – jogi

1

Sé que no es aficionado a la idea envoltorio, pero hay una solución que utiliza tanto un envoltorio pero también usa los atributos xml que son muy fáciles de usar. Mi negativa a utilizar el siguiente enfoque es el uso del antiguo serializador.

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

Ahora su controlador solo puede devolver los productos como:

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

ahora puede especificar el serializador en la puesta en marcha de este modo:

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

Sé que no es el más La forma ideal de tener que especificar el serializador y perder la flexibilidad y conveniencia de EF y Linq. O al menos tener que intervenir en lugar de solo devolver IEnumerable <>.

me tienen que dar crédito a la siguiente dirección como supe por primera vez de esta manera desde el sitio en: http://justthisguy.co.uk/outputting-custom-xml-net-web-api/

Esto dará lugar a la siguiente 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> 

Por favor, no se olvide para mirar el sitio mencionado.

1

Como esquiva dicho ....

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

Si usted está teniendo problemas debido a que es un método, a continuación, intente volver a definirlo como una propiedad, ya que no toma parámetros, y probablemente tiene más sentido.

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

que listará todas Product elementos dentro de un elemento llamado elemento de 'Productos'.

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

P.S. Para cambiar el nombre de las etiquetas de elemento Product, puede usar el atributo [XmlArrayItem("Product")] para hacer esto. Si desea tener una lista plana (no las ajuste en 'Productos'), puede usar el [XmlElement("Product")] y las listará sin agruparlas.

+1

Hola. Este código me da un error "el xmlarray no es válido en este tipo de declaración". ¿Puedes sugerir una salida? –

Cuestiones relacionadas