Removing XML deserialization from HttpWebResponse GetResponseStream with various types

I'm calling the web service. He accepts the Http message. This is plain XML over Http. You send him an XML request document to the request body, you return an XML response document in the main part of the response. I have a good library in our code base that we have built over the years, which is gaining a lot of serialization for both request documents and responses. Everything is working fine.

Now a new service with which I integrate does not always return the same type of object in response. Under certain error conditions, a special document with an error is returned. Of course, in these situations, my deserialization fails and the response data is lost. I know that I have a deserialization errror, but since the answer is lost, I don't know what the reason was.

I think the problem is that the stream returned by GetResponseStream () does not support search operations, so when I get an error, I cannot just rewind the stream and re-read the data and process it differently.

I am looking for strategies to better deal with this.

I think what I'm going to do is copy the response stream to the memory stream that can be found before I try to deserialize. Then, if an error occurs, I can rewind the memory stream and process the response data in different ways. There was a good example in https://stackoverflow.com> .

Is there a better way to do this? It seems wasteful to copy the response stream to the memory stream.

A simplified version of the source 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;
    }
}

A simplified version of the proposed 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;
      }
    }
}
+3
source share
2 answers

If the returned XML error has a different root element, you can use the method XmlSerializer.CanDeserializebefore the actual deserialization.

+2
source

, , , / . :

 public string RetrieveResponse()
        {

            //Create a new http request
            HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create("http://example.com/service"); ;

            Stream responseStream = null;
            try
            {

                using (var httpResponse = (HttpWebResponse)httpRequest.GetResponse())
                {
                    responseStream = httpResponse.GetResponseStream();

                    if (responseStream == null)
                    {
                        return null;
                    }

                    using (var streamRdr = new StreamReader(responseStream))
                    {
                        var response = streamRdr.ReadToEnd();

                        httpResponse.Close();

                        return response;
                    }
                }

            }
            finally
            {
                if (responseStream != null)
                {
                    responseStream.Dispose();
                }


            }
        }

, , :

private  AccountResponse LoadFromString(string response)
        {
            if (string.IsNullOrEmpty(response))
                return null;


            try
            {
                AccountResponse result = null;
                using (var stringReader = new StringReader(response))
                {
                    using (XmlReader reader = new XmlTextReader(stringReader))
                    {
                        var serializer = new XmlSerializer(typeof(AccountResponse));
                        result = serializer.Deserialize(reader) as AccountResponse;
                    }
                }

                return result;
            }
            catch (Exception exception)
            {
                //Log the exception, etc.

            }

        }

PS: , , , . , .

+1

All Articles