Параметр POST AspNet WebApi при отправке XML
У меня есть служба веб-api, первоначально использующая бета-биты, которые я перестроил с использованием бит-релиза релиза, и теперь у меня есть эта проблема.
У меня есть действие POST, которое принимает сложный параметр как единственный параметр. Когда я отправляю запрос с телом в формате json, объект десериализуется, как ожидалось, но если я отправлю XML вместо этого параметра, то он будет равен нулю.
В бета-версии я работал над этим, отключив привязку модели, как описано в сообщении блога Carlos Figueira Отключение привязки модели к бета-версии веб-API ASP.NET
В RC, однако, они удалили IRequestContentReadPolicy, который этот метод реализует.
Мое действие:
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;
}
}
Моя модель:
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; }
}
Я тестирую использование Fiddler для отправки запросов в службу.
Это работает и возвращает мне ожидаемые результаты.
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"
}
]
}
Это не работает, потому что параметр requestValues имеет значение 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>
Ответы
Ответ 1
Добавив следующие строки к методу ApplicationStart() в вашем
Global.asax.cs, ваш исходный запрос XML должен работать:
var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
xml.UseXmlSerializer = true;
По умолчанию веб-API использует класс DataContractSerializer, который требует дополнительной информации в запросе XML.
XmlSerializer, кажется, работает более плавно для меня, так как мне не нужно добавлять имя модели к каждому запросу XML.
Еще раз, я нашел свою информацию в статье Майка Уосона: http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization#xml_media_type_formatter
Ответ 2
У меня была та же проблема, что и у вас, и нашел решение путем сериализации объекта с помощью XmlMediaTypeFormatter, как описано здесь: http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization#testing_object_serialization. Я использовал код в разделе "Сериализация объектов тестирования" в нижней части статьи и заменил его объект Person моей моделью.
Когда я сериализовал свой объект, я заметил, что в корневой каталог node были добавлены следующие атрибуты:
xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/NAMESPACE.OF.YOUR.MODEL"
Если вы добавляете эти атрибуты в свой xml, так и ваш, ваш контроллер должен правильно сериализовать объект 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>