Как я могу POST (как XML) объект к моему ApiController, используя RestSharp?
У меня есть веб-сайт ASP.NET MVC4, реализующий API REST, который я использую из клиентского приложения. Мои методы ApiController принимают и возвращают сложные объекты в виде XML.
Недавно я обнаружил RestSharp и начал перекладывать свой клиентский проект на это. Однако у меня есть реальные проблемы с этим. Кажетсяalmost работа - это так близко, что я почти чувствую вкус успеха - но я просто не могу заставить его работать на 100%.
Объекты, которые я передаю через провод, выглядят примерно так:
// The object I'm passing across the wire
public class Example
{
bool IsActive { get; set; }
string Name { get; set; }
}
Мой метод ApiController выглядит так:
// My ApiController method
public HttpResponseMessage PostExample(Example example)
{
if (ModelState.IsValid)
{
db.Examples.Add(example);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, example);
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
Проблема возникает, когда я пытаюсь разместить объект на моем сайте, например:
var example = new Example () { IsActive = true, Name = "foo" };
var request = new RestSharp.RestRequest("/api/example", RestSharp.Method.POST);
request.AddBody(example, XmlNamespace);
var client = new RestClient();
client.BaseUrl = "foo.com";
var response = client.Execute<Example>(request);
Приведенный выше код выполняет метод PostExample в моем ApiController, и в качестве параметра у него есть объект Example.However значения свойств объекта Example не совпадают со значениями, которые я передал методу Execute! В одном случае член IsActive был ложным, а не истиной, хотя я также видел случай, когда член имени был нулевым, где он должен был иметь значение.
Я провел некоторое исследование с использованием Fiddler, и кажется, что правильные значенияare создается в XML, который генерирует RestSharp. Тем не менее, XML не совсем в том же формате, который веб-сервер выдает при выполнении GET. Различия невелики, но, похоже, делают различие между тем, что работает, а что нет. Платформа на стороне веб-сервера, кажется, чувствительна к этим различиям форматирования и в результате неправильно интерпретирует XML.
Вот XML, который я получаю от RestSharp:
<Example xmlns="http://schemas.datacontract.org/2004/07/ExampleNamespace">
<Name>foo</Name>
<IsActive>true</IsActive>
</Example>
Вот что я получаю при выполнении GET на веб-сервере (или при сериализации с использованием DataContractSerializer, что я и делал ранее):
<Example xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ExampleNamespace">
<IsActive>true</IsActive>
<Name>foo</Name>
</TagDto>
Версия RestSharp имеет следующие отличия от версии DataContractSerializer:
Fields are in a different order RestSharp doesn't include the extra namespace XMLSchema-instance namespace DataContractSerializer doesn't include any spaces or line-breaks (I added those above for readability)Я удивлен, что любой из них имеет большое значение, но ясно, что они делают. Также обратите внимание, что до тех пор, пока я не добавил явное пространство имен в вызове AddBody, оно отсутствовало в сгенерированном XML (очевидно), и объект Example, переданный в мой ApiController, былnull
.
В любом случае, я заметил, что RestSharp позволяет вам переопределять сериализатор и предоставляет способ использования .NET XML сериализатора. Я пытался использовать это (безрезультатно).
Это то, что я добавил перед вызовом AddBody:
request.XmlSerializer = new RestSharp.Serializers.DotNetXmlSerializer(XmlNamespace);
..и вот что я получаю:
<?xml version="1.0" encoding="utf-8"?>
<Example>
<Name>foo</Name>
<IsActive>true</IsActive>
</Example>
Это явно не хорошо, не в последнюю очередь потому, что начинается с объявления XML, которое я представляюwould вызвать проблемы. Отключить это невозможно, потому что производный класс RestSharp не предоставляет этого. Кроме того, нет пространства имен - и я не могу заставить его появляться в выходных данных, независимо от того, как я пытаюсь установить пространство имен в RestSharp (в конструкторе для DotNetXmlSerializer, устанавливая член пространства имен или передавая пространство имен для AddBody). На мой взгляд, этот класс - не более чем ловушка.
Похоже, мой единственный вариант - создать свой собственный класс сериализатора и использовать DataContractSerializer внутри. Это правильно, или я что-то упустил?
(Кстати, я могу установить RequestFormat запроса в JSON, и он просто работает, но я все еще хотел бы знать, как заставить это работать с XML).