10
votes

I have the following XML response I am trying to deserialize using XmlSerializer. When I remove the call to XML serializer I throw no errors. Every time I use XmlSerializer I get an exception. What am I missing?

Exception is:

System.Xml.XmlException: Root element is missing.
  at System.Xml.XmlTextReaderImpl.Throw(Exception e)
  at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
  at System.Xml.XmlTextReaderImpl.Read()
  at System.Xml.XmlTextReader.Read()
  at System.Xml.XmlReader.MoveToContent()
  at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderSubmitReportResponse.Read5_NeweggAPIResponse()

Xml Doc is:

<?xml version="1.0" encoding="utf-8"?>
<NeweggAPIResponse>
    <IsSuccess>true</IsSuccess>
    <OperationType>OrderListReportResponse</OperationType>
    <SellerID>myID</SellerID>
    <ResponseBody>
        <ResponseList>
            <ResponseInfo>
                <RequestId>XXXXXXXX</RequestId>
                <RequestType>ORDER_LIST_REPORT</RequestType>
                <RequestDate>07/26/2012 09:27:06</RequestDate>
                <RequestStatus>SUBMITTED</RequestStatus>
            </ResponseInfo>
        </ResponseList>
    </ResponseBody>
</NeweggAPIResponse>

My call to XmlSerializer is:

XmlSerializer serializer = new XmlSerializer(typeof(SubmitReportResponse));
reportReq = serializer.Deserialize(respStream) as SubmitReportResponse;

SubmitReportResponse class is:

    public enum RequestStatus
{
    ALL,
    SUBMITTED,
    IN_PROGRESS,
    FINISHED,
    CANCELLED
}

/// <summary>
/// TODO: Update summary.
/// </summary>
[XmlRoot("NeweggAPIResponse")]
public class SubmitReportResponse
{
    public string IsSuccess { get; set; }
    public string OperationType { get; set; }
    public string SellerID { get; set; }
    public ReportResponseBody ResponseBody { get; set; }

    public SubmitReportResponse()
    {
        ResponseBody = new ReportResponseBody();
    }
}

public class ReportResponseBody
{
    public string Memo { get; set; }
    public ReportResponseList[] ResponseList { get; set; }   



    public ReportResponseBody()
    {

        ResponseList = new ReportResponseList[0];
    }
}

public class ReportResponseList
{
    public ResponseInfo[] ResponseInfo { get; set; }

    public ReportResponseList()
    {
        ResponseInfo = new ResponseInfo[0];
    }

}

public class ResponseInfo
{
    public string RequestId { get; set; }
    public string RequestType { get; set; }
    public string RequestDate { get; set; }
    public RequestStatus RequestStatus { get; set; }

    public ResponseInfo()
    {
        RequestStatus = new RequestStatus();
    }
}

EDIT:

Requesting Code:

            HttpWebRequest request = WebRequest.Create(endpoint) as HttpWebRequest;
            request.Proxy = null;
            request.Method = "POST";
            //Specify the xml/Json content types that are acceptable. 
            request.ContentType = "application/xml";
            request.Accept = "application/xml";

            //Attach authorization information
            request.Headers.Add("Authorization", apikey);
            request.Headers.Add("Secretkey", secretkey);

            GetOrderListRequest requestObj = new GetOrderListRequest();
            requestObj.OperationType = OperationType.OrderListReportRequest;
            requestObj.RequestBody = new OrderListRequestBody();
            requestObj.RequestBody.OrderReportCriteria = new OrderReportCriteria();
            requestObj.RequestBody.OrderReportCriteria.Status = 3;
            requestObj.RequestBody.OrderReportCriteria.KeywordsType = 0;
            requestObj.RequestBody.OrderReportCriteria.OrderDateFrom = "2012-01-01";
            requestObj.RequestBody.OrderReportCriteria.OrderDateTo = "2012-07-26";
            requestObj.RequestBody.OrderReportCriteria.OrderDownloaded = "false";

            string requestBody = SerializeToString(requestObj);

            byte[] byteStr = Encoding.UTF8.GetBytes(requestBody);
            request.ContentLength = byteStr.Length;

            using (Stream stream = request.GetRequestStream())
            {
                stream.Write(byteStr, 0, byteStr.Length);
            }

            //Parse the response
            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                //Business error
                if (response.StatusCode != HttpStatusCode.OK)
                {
                    Console.WriteLine(string.Format("Error: response status code is{0}, at time:{1}", response.StatusCode, DateTime.Now.ToString()));

                    return;
                }
                else if (response.StatusCode == HttpStatusCode.OK)//Success
                {
                    using (Stream respStream = response.GetResponseStream())
                    {
                        StreamReader readerOK = new StreamReader(respStream);
                        //Console.WriteLine(String.Format("Result:{0}", DateTime.Now.ToString()));
                        Console.WriteLine(String.Format("{0}", readerOK.ReadToEnd()));

                        XmlSerializer serializer = new XmlSerializer(typeof(SubmitReportResponse));
                        reportReq = serializer.Deserialize(respStream) as SubmitReportResponse;
                    }
                }
            }


    public string SerializeToObj(object obj)
    {

        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("", "");
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.OmitXmlDeclaration = true;
        settings.Encoding = new UTF8Encoding(false);
        settings.Indent = true;
        XmlSerializer xs = new XmlSerializer(obj.GetType());
        MemoryStream ms = new MemoryStream();

        // xs.Serialize(ms, obj,ns);


        XmlWriter writer = XmlWriter.Create(ms, settings);
        xs.Serialize(writer, obj, ns);

        return Encoding.UTF8.GetString(ms.ToArray());
    }

Resolution:

It seems that calling Console.WriteLine(String.Format("{0}", readerOK.ReadToEnd())); causes the stream to be consumed and be unavailable for serialization. Removing this line allowed me to properly serialize the XML into my classes.

1
Try changing the XmlRoot("NeweggAPIResponse") to XmlType("NeweggAPIResponse"). - Stephan
Can I see the code where you retrieve the actual XML please? I've tested your code locally and it works if I load the XML file from the disk, but with the caveat that you don't need the intermediate ReportResponseList class. - dash
@dash Added calling code. Please see edit. Stephan: That didn't work. - Robert H
Are you certain that the XML is as you expect? Chances are that the root element is actually missing (i.e., the XML is empty). - John Saunders
@JohnSaunders Now you have made me doubt myself lol. Let me check - Robert H

1 Answers

17
votes

Calling Console.WriteLine(String.Format("{0}", readerOK.ReadToEnd())); causes the stream to be consumed and be unavailable for serialization.

Removing this line allowed me to properly serialize the XML into my classes.