2012-06-21 19 views
23

Tengo un servicio web API que originalmente utilizaba bits beta que he reconstruido utilizando los bits de lanzamiento candidato y ahora estoy teniendo este problema.AspNet WebApi POST parámetro es nulo al enviar XML

Tengo una acción POST que toma una opción compleja como único parámetro. Cuando envío la solicitud con el cuerpo en formato json, el objeto se deserializa como se esperaba, pero si envío XML en su lugar, el parámetro es nulo.

En la versión beta trabajé en torno a este mediante la desactivación de unión como se describe en el blog de Carlos Figueira Disabling model binding on ASP.NET Web APIs Beta

En el RC sin embargo han eliminado la IRequestContentReadPolicy que este método se implementa modelo.

Mi acción:

public List<Models.Payload> Post([FromBody]Models.AimiRequest requestValues) 
{ 
    try 
    { 
    if (requestValues == null) 
    { 
     var errorResponse = new HttpResponseMessage(); 
     errorResponse.StatusCode = HttpStatusCode.NotFound; 
     errorResponse.Content = new StringContent("parameter 'request' is null"); 
     throw new HttpResponseException(errorResponse); 
    } 
    var metadataParams = new List<KeyValuePair<string, string>>(); 
    foreach (Models.MetadataQueryParameter param in requestValues.Metadata) 
    { 
     metadataParams.Add(new KeyValuePair<string, string>(param.Name, param.Value)); 
    } 
    List<Core.Data.Payload> data = _payloadService.FindPayloads(metadataParams, requestValues.ContentType, requestValues.RuleTypes); 
    var retVal = AutoMapper.Mapper.Map<List<Core.Data.Payload>, List<Models.Payload>>(data); 
    return retVal; // new HttpResponseMessage<List<Models.Payload>>(retVal); 
    } 
    catch (System.Exception ex) 
    { 
    _logger.RaiseError(ex); 
    throw; 
    } 
} 

Mi modelo:

public class AimiRequest 
{ 
    public MetadataQueryParameter[] Metadata { get; set; } 
    public string ContentType { get; set; } 
    public string RuleTypes { get; set; } 
} 

public class MetadataQueryParameter 
{ 
    public string Name { get; set; } 
    public string Value { get; set; } 
} 

Estoy probando el uso de Fiddler para enviar solicitudes al servicio.

Esto funciona y me devuelve los resultados esperados.

POST http://localhost:51657/api/search HTTP/1.1 
User-Agent: Fiddler 
Content-Type: application/json; charset=utf-8 
Accept: application/json 
Host: localhost:51657 
Content-Length: 219 

{ 
    "ContentType":null, 
    "RuleTypes":null, 
    "Metadata":[ 
    { 
    "Name":"ClientName", 
    "Value":"Client One" 
    }, 
    { 
    "Name":"ClientName", 
    "Value":"Client Two" 
    } 
    ] 
} 

esto falla porque el parámetro es nulo requestValues ​​

POST http://localhost:51657/api/search HTTP/1.1 
User-Agent: Fiddler 
Content-Type: application/xml; charset=utf-8 
Accept: application/xml 
Host: localhost:51657 
Content-Length: 213 

<AimiRequest> 
    <ContentType /> 
    <RuleTypes /> 
    <Metadata> 
    <MetadataQueryParameter> 
     <Name>ClientName</Name> 
     <Value>Client One</Value> 
    </MetadataQueryParameter> 
    <MetadataQueryParameter> 
     <Name>ClientName</Name> 
     <Value>Client Two</Value> 
    </MetadataQueryParameter> 
    </Metadata> 
</AimiRequest> 
+0

Ver detalles en esta [pregunta] [1] ... [1]: http://stackoverflow.com/questions/14068288/model-always-null-on-xml-post – barrypicker

Respuesta

24

al añadir las siguientes líneas al método ApplicationStart() en sus Global.asax.cs, su solicitud XML original debería funcionar:

var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter; 
xml.UseXmlSerializer = true; 

De forma predeterminada, la API web utiliza la clase DataContractSerializer, que requiere información adicional en la solicitud XML.

El XmlSerializer parece funcionar más fácilmente para mí, ya que no tengo que agregar el nombre del modelo a cada solicitud XML.

Una vez más, me encontré con mi información en el artículo de Mike Wasson: http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization#xml_media_type_formatter

+0

esta era la solución que estaba buscando.Tuve el mismo problema donde json funcionaría bien, pero el objeto siempre sería nulo cuando usase xml –

+0

que no funcionaba para mí. ahora la aplicación está devolviendo "El tipo de medio de la entidad de solicitud 'application/xml' no es compatible con este recurso.". – gkon

5

que estaba teniendo el mismo problema que tú, y encontró la solución serializando el objeto con la XmlMediaTypeFormatter como se describe aquí: http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization#testing_object_serialization. Usé el código en la sección "Serialización de objetos de prueba" en la parte inferior del artículo, y reemplacé su objeto Person con mi modelo.

Cuando serializado mi objetivo, he notado que los atributos siguientes se añadieron al nodo raíz:

xmlns:i="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://schemas.datacontract.org/2004/07/NAMESPACE.OF.YOUR.MODEL" 

Si agrega estos atributos para el código XML como tal, su controlador debe serializar correctamente objeto los requestValues:

<AimiRequest xmlns:i="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://schemas.datacontract.org/2004/07/NAMESPACE.OF.YOUR.MODEL"> 
    <ContentType /> 
    <RuleTypes /> 
    <Metadata> 
    <MetadataQueryParameter> 
     <Name>ClientName</Name> 
     <Value>Client One</Value> 
    </MetadataQueryParameter> 
    <MetadataQueryParameter> 
     <Name>ClientName</Name> 
     <Value>Client Two</Value> 
    </MetadataQueryParameter> 
    </Metadata> 
</AimiRequest> 
Cuestiones relacionadas