Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AspNet WebApi POST parameter is null when sending XML

Tags:

I have a web api service originally using beta bits which I've rebuilt using the release candidate bits and I'm now having this problem.

I have a POST action that takes a complex option as the only parameter. When I send the request with the body in json format the object is deserialised as expected, but if I send XML instead the parameter is null.

In the beta I worked around this by disabling model binding as described in Carlos Figueira's blog post Disabling model binding on ASP.NET Web APIs Beta

In the RC however they have removed the IRequestContentReadPolicy that this method was implementing.

My action:

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

My model:

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

I'm testing using Fiddler to send requests to the service.

This works and returns me the expected results.

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"     }   ] } 

This fails because the requestValues parameter is null

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> 
like image 725
Nick Avatar asked Jun 21 '12 16:06

Nick


1 Answers

By adding the following lines to the ApplicationStart() method in your Global.asax.cs, your original XML request should work:

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

By default, the Web API uses the DataContractSerializer class, which requires extra information in the XML request.

The XmlSerializer seems to work more smoothly for me, since I don't have to add the model's namepsace to each XML request.

Once again, i found my information in Mike Wasson's article: http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization#xml_media_type_formatter

like image 61
matthughes404 Avatar answered Oct 06 '22 02:10

matthughes404