Serialize XmlDocument & send via HTTPWebRequest

2019-02-28 20:02发布

问题:

I'm trying to figure out how to properly serialize my XmlDocument and send it via a HTTPWebRequest object.

Here's what I have thus far:

Stream requestStream;

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://wwwcie.ups.com/ups.app/xml/Track");
request.Method = "POST";

request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postData.Length;
requestStream = request.GetRequestStream();

XmlSerializerNamespaces xsm = new XmlSerializerNamespaces();
xsm.Add("", ""); // remove namespace
XmlSerializer ser = new XmlSerializer(xmlRequest.GetType());
ser.Serialize(requestStream, xmlRequest);

requestStream.Write(postData, 0, postData.Length);
requestStream.Close();

A few things I'm uncertain about. I have 2 XmlDocuments I need to send in the same HTTPWebRequest. I've tried before to convert the XmlDocuments to strings and just concatenate them (to send the string) but when I used the StringBuilder / Writer it adds:

  <?xml version="1.0" encoding="utf-8" ?> 
  <string xmlns="http://myNameSpace/">

I already have the declaration in my XmlDocument objects so now its in there twice, and I cannot have the <string... part in there. Is it easier to convert the XmlDocuments to strings then concatenate them and send that or is there a easy way to send the XmlDocuments as they are?

Edit:

See C# XmlDocument Nodes When I try to convert one of my XmlDocuments to a string it shows up as

  <?xml version="1.0" encoding="utf-8" ?> 
  <string xmlns="http://myNamespace/">
      <TrackRequest>
         <Request>
            <TransactionReference>
                <CustomerContext>whatever</CustomerContext>
            </TransactionReference>
         </Request>
         <TrackingNumber>123</TrackingNumber>
      </TrackRequest>
   </string> 

I want my root to be <TrackRequest>

回答1:

I'm guessing this question is related to the previous one about 2 xml documents not being able to be combined into one document without wrapping them both in a root node first (C# XmlDocument Nodes).

If that is the case then you don't want to be serialising the XmlDocuments and sending them to the WebService. Serializing the objects is for transporting/storing the actual object, not the data. You want to just send the webservice the data not the object so just concatenate the two xml documents and send that.

use XmlDocument.OuterXml to get the XmlDocument as a string. ie:

XmlDocument doc1 = new XmlDocument();
doc.LoadXml("Some XML");
XmlDocument doc2 = new XmlDocument();
doc2.LoadXml("Some other XML");
StringBuilder sb = new StringBuilder();
sb.Append(doc1.OuterXml);
sb.Append(doc2.OuterXml);

The just send sb.ToString() to the WebService.

Hope I haven't got completely the wrong end of the stick.



回答2:

Works (somewhat)! Thanks, heres the code:

Stream requestStream;
Stream responseStream;
WebResponse response;
StreamReader sr;
byte[] postData;
string postString;
postString = xmlAccess.OuterXml + xmlRequest.OuterXml;
postData = Encoding.UTF8.GetBytes(postString);

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://wwwcie.ups.com/ups.app/xml/Track");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postData.Length;
requestStream = request.GetRequestStream();

requestStream.Write(postData, 0, postData.Length);
requestStream.Close();

response = request.GetResponse();
responseStream = response.GetResponseStream();
sr = new StreamReader(responseStream);

return sr.ReadToEnd();

It still doesnt return proper XML though:

<?xml version="1.0" encoding="utf-8" ?> 
  <string xmlns="http://namespace/"><?xml version="1.0" ?> <TrackResponse><Response><...

Not sure why there's 2x <?xml version...



回答3:

I'm doing this now with UPS, instead of building the documents in XML, I just used string builders like so:

... in code:

AddNode("name", "value");

...in class:

private StringBuilder sb;
public void AddNode(string name, string value) 
{
    sb.Append("<" + name + ">" + value + "</" + name + ">");
}

I personally think it's better, because it reduces the server load.