Wie kann ich mit RestSharp ein Objekt an meinen ApiController POSTEN (als XML)?

Ich habe eine ASP.NET MVC4-Website, auf der eine REST-API implementiert ist, die ich von einer Clientanwendung verwende. Meine ApiController-Methoden nehmen und geben komplexe Objekte als XML zurück.

Ich habe vor kurzem RestSharp entdeckt und damit begonnen, mein Kundenprojekt darauf umzustellen. Ich habe jedoch echte Probleme damit. Es sieht so ausfast Arbeit - es ist so nah, dass ich beinahe den Erfolg schmecken kann - aber ich kann es einfach nicht zu 100% zum Arbeiten bringen.

Die Objekte, die ich über das Kabel bewege, sehen ungefähr so ​​aus:

// The object I'm passing across the wire
public class Example
{
    bool IsActive { get; set; }
    string Name { get; set; }
}

Meine ApiController-Methode sieht folgendermaßen aus:

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

Das Problem tritt wie folgt auf, wenn ich versuche, ein Objekt auf meiner Website zu veröffentlichen:

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

Der obige Code entspricht der PostExample-Methode in meinem ApiController und hat ein Example-Objekt als Parameter.jedoch Die Werte der Eigenschaften des Example-Objekts stimmen nicht mit denen überein, die ich an die Execute-Methode übergeben habe! In einem Fall war das IsActive-Mitglied falsch statt wahr, obwohl ich auch einen Fall gesehen habe, in dem das Name-Mitglied null war und einen Wert hätte haben sollen.

Ich habe mit Fiddler nachgeforscht, und es scheint, dass die Werte stimmensind Wird in der von RestSharp generierten XML erstellt. Das XML hat jedoch nicht ganz dasselbe Format, das der Webserver beim Ausführen eines GET ausgibt. Die Unterschiede sind subtil, scheinen aber den Unterschied zwischen funktionieren und nicht funktionieren zu machen. Das Framework am Ende des Webservers scheint für diese Formatierungsunterschiede empfänglich zu sein und interpretiert das XML daher falsch.

Hier ist das XML, das ich von RestSharp bekomme:

<Example xmlns="http://schemas.datacontract.org/2004/07/ExampleNamespace">
  <Name>foo</Name>
  <IsActive>true</IsActive>
</Example>

Folgendes erhalte ich, wenn ich ein GET auf dem Webserver durchführe (oder wenn ich mit dem DataContractSerializer serialisiere, was ich zuvor getan habe):

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

Die RestSharp-Version unterscheidet sich wie folgt von der DataContractSerializer-Version:

Felder sind in einer anderen ReihenfolgeRestSharp enthält keinen zusätzlichen Namespace für XMLSchema-InstanzenDer DataContractSerializer enthält keine Leerzeichen oder Zeilenumbrüche (ich habe diese zur besseren Lesbarkeit hinzugefügt)

Ich bin überrascht, dass all das einen großen Unterschied macht, aber es ist klar, dass dies der Fall ist. Beachten Sie auch, dass dies in der generierten XML (offensichtlich) fehlte, bis ich einen expliziten Namespace im AddBody-Aufruf hinzufügte und das Example-Objekt an meinen ApiController übergeben wurdenull.

Wie auch immer, mir ist aufgefallen, dass Sie mit RestSharp den Serializer überschreiben können und den .NET XML-Serializer verwenden können. Ich habe versucht, dies zu nutzen (ohne Erfolg).

Folgendes habe ich vor dem Aufruf von AddBody hinzugefügt:

request.XmlSerializer = new RestSharp.Serializers.DotNetXmlSerializer(XmlNamespace);

..und das bekomme ich raus:

<?xml version="1.0" encoding="utf-8"?>
<Example>
  <Name>foo</Name>
  <IsActive>true</IsActive>
</Example>

Dies ist eindeutig nicht gut, nicht zuletzt, weil es mit einer XML-Deklaration beginnt, die ich mir vorstellewürde Probleme verursachen. Es gibt keine Möglichkeit, dies zu deaktivieren, da die abgeleitete RestSharp-Klasse keine Möglichkeit bietet, dies zu tun. Außerdem gibt es keinen Namespace - und ich kann keinen in der Ausgabe anzeigen, egal wie ich versuche, den Namespace in RestSharp festzulegen (im Konstruktor für den DotNetXmlSerializer, indem Sie das Namespace-Member festlegen oder einen Namespace an übergeben AddBody). Für mich ist diese Klasse nichts anderes als eine Falle.

Es sieht so aus, als ob meine einzige Option darin besteht, eine eigene Serializer-Klasse zu erstellen und den DataContractSerializer intern zu verwenden. Ist das richtig oder fehlt mir etwas?

(Übrigens, ich kann das RequestFormat der Anfrage auf JSON setzen und es funktioniert einfach - aber ich möchte immer noch wissen, wie dies mit XML funktioniert).

Antworten auf die Frage(2)

Ihre Antwort auf die Frage