웹 서비스를 호출하고 있습니다. 그것은 Http Post를 허용합니다. 그것은 HTTP를 통해 간단한 XML입니다. 요청 본문에 XML 요청 문서를 보내면 응답 본문에 XML 응답 문서가 반환됩니다. 필자는 수년 동안 요청 및 응답 문서 모두에 대해 강력하게 형식화 된 serialization을 작성한 코드 기반의 멋진 라이브러리를 보유하고 있습니다. 모든 것이 정상적으로 작동합니다.다른 형식의 HttpWebResponse GetResponseStream에서 XML 비 직렬화
이제 내가 통합 할 새 서비스가 항상 응답에서 동일한 객체 유형을 다시 보내는 것은 아닙니다. 특정 오류 조건에서 특수 오류 문서를 반환합니다. 물론 이러한 상황에서 내 deserialization이 실패하고 응답 데이터가 손실됩니다. deserialization errror가 있다는 것을 알고 있지만 응답이 없어지기 때문에 근본 원인이 무엇인지 알 수 없습니다.
GetResponseStream()에 의해 반환 된 스트림이 탐색 작업을 지원하지 않는다고 생각합니다. 그래서 오류가 발생하면 단순히 스트림을 되감거나 데이터를 다시 읽고 다르게 처리 할 수 없습니다.
나는 이것을 더 잘 다루는 전략을 찾고있다.
제가 생각하기에 나는 deserialize하기 전에 seekable 인 메모리 스트림에 응답 스트림을 복사하는 것이라고 생각합니다. 그런 다음 오류가 발생하면 메모리 스트림을 되감기하고 응답 데이터를 다르게 처리 할 수 있습니다. https://stackoverflow.com/a/3434077/90236에 좋은 예가있었습니다.
더 좋은 방법이 있나요? 응답 스트림을 메모리 스트림에 복사하는 것은 낭비입니다. 원래 코드의 versioin 단순화
:
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;
}
}
제안 코드의
단순화 된 버전
: 당신이 할 수있는 것은 전체 스트림을 읽을
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;
}
}
}
감사합니다. 불행히도 CanDeserialize 테스트를 추가하는 것이 매우 어렵습니다. 그래서 지금은 스트림 복사본 접근 방식을 유지할 것입니다. 그러나 이것이 올바른 대답이라고 생각합니다. –