Deserialisieren von XML-Daten von HttpWebResponse GetResponseStream mit verschiedenen Arten
Ich bin Aufruf eines web service. Akzeptiert er Http-Post. Es ist einfach, XML-über-Http. Sie senden eine XML-Anfrage-Dokument in den Körper der Anfrage, erhalten Sie eine XML-Antwort-Dokument in den Text der Antwort. Ich habe eine schöne Bibliothek in unserer code-Basis, die wir aufgebaut haben über die Jahre nicht stark typisiert Serialisierung sowohl die Anfrage-und Antwort-Dokumente. Alles normal funktioniert.
Nun ist der neue service, den ich bin die Integration mit nicht senden immer wieder die gleichen Objekt-Typ in der Antwort. Unter bestimmten Bedingungen Fehler gibt es einen speziellen Fehler-Dokument. Natürlich, in diesen Situationen mein Deserialisierung schlägt fehl, und die Antwort-Daten verloren gehen. Ich weiß, dass ich eine Deserialisierung errror, aber da die Antwort verloren gegangen ist, ich weiß nicht, was die Ursache war.
Ich denke, das problem ist, dass der stream zurückgegeben GetResponseStream() nicht unterstützt seek-Operationen, so dass, wenn ich einen Fehler ich kann nicht einfach Zurückspulen des Streams und re-die Daten Lesen und verarbeiten es anders.
Ich bin auf der Suche nach Strategien, um besser damit umgehen.
Was ich denke, ich werde zu tun ist, kopieren Sie den response-stream ein Speicher-stream, die ist seekable bevor ich Versuch zu Deserialisieren. Dann, wenn ein Fehler Auftritt, kann ich Zurückspulen des Speicher-stream und verarbeiten der Antwortdaten anders. Es war ein gutes Beispiel in https://stackoverflow.com/a/3434077/90236.
Gibt es einen besseren Weg, dies zu tun? Es scheint Art von Verschwendung zu kopieren Sie den response-stream ein Speicher-stream.
Vereinfachte versioin der original-code:
AccountRequest requestVal = new AccountRequest();
//initialize requestVal object
var request = (HttpWebRequest)WebRequest.Create("http://example.com/service");
request.Method = "POST";
request.ContentType = "text/xml";
using (Stream webStream = request.GetRequestStream())
{
var serializer = new XmlSerializer(typeof(AccountRequest));
serializer.Serialize(webStream, requestVal);
webStream.Flush();
webStream.Close();
}
AccountResponse returnVal;
using (var response = (HttpWebResponse)request.GetResponse())
{
Stream responseStream = response.GetResponseStream();
var serializer = new XmlSerializer(typeof(responseStream));
try
{
returnVal = (AccountResponse)serializer.Deserialize(responseStream);
}
catch (Exception ex)
{
//if an exception occurs, the response stream data is lost.
//The responseStream is not seekable.
logger.ErrorFormat("After Exception:\n{0}", ex.ToString());
throw;
}
}
Vereinfachte version des vorgeschlagenen code:
AccountRequest requestVal = new AccountRequest();
//initialize requestVal object
var request = (HttpWebRequest)WebRequest.Create("http://example.com/service");
request.Method = "POST";
request.ContentType = "text/xml";
using (Stream webStream = request.GetRequestStream())
{
var serializer = new XmlSerializer(typeof(AccountRequest));
serializer.Serialize(webStream, requestVal);
webStream.Flush();
webStream.Close();
}
AccountResponse returnVal;
using (var response = (HttpWebResponse)request.GetResponse())
{
Stream responseStream = response.GetResponseStream();
using (MemoryStream ms = new MemoryStream())
{
//copy response stream to a seekable memorystream
int count = 0;
do
{
byte[] buf = new byte[1024];
count = responseStream.Read(buf, 0, 1024);
ms.Write(buf, 0, count);
} while (responseStream.CanRead && count > 0);
ms.Position = 0;
//now attempt to desrialize from the memory stream
var serializer = new XmlSerializer(typeof(AccountResponse));
try
{
returnVal = (AccountResponse)serializer.Deserialize(ms);
}
catch (Exception ex)
{
//if an exception occured, rewind the stream and write an error to the log
ms.Position = 0;
using (var reader = new StreamReader(ms, Encoding.UTF8))
{
logger.ErrorFormat("After Exception:\n{0}\n\nRespons:\n{1}",
ex.ToString(), reader.ReadToEnd());
}
throw;
}
}
}
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn das zurückgegebene XML-Fehler hat eine andere root-element können Sie die
XmlSerializer.CanDeserialize
Methode, bevor Sie tatsächlich zu Deserialisieren.Anstelle von kopieren der stream, was Sie tun können, ist zu Lesen, der gesamte stream als string zuerst, und dann Deserialisieren/schreiben von Protokollen, wie erforderlich. Unten sind code-snippets:
Als Nächstes können Sie Deserialisieren mit der Antwort zurück, snippet unter:
PS: wenn Sie wissen, das format der Fehler, der zurückgegeben wird, indem Sie das service Sie sind wirklich in der Lage, zu Deserialisieren der Fehler zu einem Objekt als auch in einem gehen, so dass wir nicht haben, um zu versuchen und zu fangen. Hoffe, das hilft.