.NET:将Xml发布到Web服务器?

时间:2010-10-07 17:22:40

标签: .net xml xml-serialization xmlhttprequest

XmlDocument发布到网络服务器的正确方法是什么?这是骨架功能:

public static void PostXml(XmlDocument doc, String url)
{ 
   //TODO: write this
}

现在我使用:

//Warning: Do not use this PostXml implmentation
//It doesn't adjust the Xml to match the encoding used by WebClient
public static void PostXml(XmlDocument doc, String url)
{
   using (WebClient wc = new WebClient())
   {
      wc.UploadString(url, DocumentToStr(doc));
   }
}

DocumentToStr是一种完全有效且正确的方法:

/// <summary>
/// Convert an XmlDocument to a String
/// </summary>
/// <param name="doc">The XmlDocument to be converted to a string</param>
/// <returns>The String version of the XmlDocument</returns>
private static String DocumentToStr(XmlDocument doc)
{
    using (StringWriter writer = new StringWriter())
    {
       doc.Save(writer);
       return writer.ToString();
    }
}

我实现PostXml的问题在于它按原样发布String 。这意味着(在我的情况下)http请求是:

POST https://stackoverflow.com/upload.php HTTP/1.1
Host: stackoverflow.com
Content-Length: 557
Expect: 100-continue

<?xml version="1.0" encoding="utf-16"?>
<AccuSpeedData MACAddress="00252f21279e" Date="2010-10-07 10:49:41:768">
  <Secret SharedKey="1234567890abcdefghijklmnopqr" />
  <RegisterSet TimeStamp="2010-10-07 10:49:41:768">
    <Register Address="total:power" Type="Analog" Value="485" />
    <Register Address="total:voltage" Type="Analog" Value="121.4" />
    <Register Address="total:kVA" Type="Analog" Value="570" />
  </RegisterSet>
</AccuSpeedData>

您会注意到xml声明的编码不正确:

<?xml version="1.0" encoding="utf-16"?>

WebClient未在utf-16 unicode中发送请求,这就是.NET中的字符串存储方式。我甚至知道 WebClient使用的编码。


xml的http帖子需要正确编码,这通常发生在调用:

期间
Save(textWriter)

在致电Save期间,XmlDocument对象将根据要求保存到的EncodingTextWriter调整xml声明。不幸的是,WebClient没有公开我可以将XmlDocument保存到的TextWriter

另见

2 个答案:

答案 0 :(得分:0)

这是solution。子类StringWriter:

public class StringWriterWithEncoding : StringWriter
{
  Encoding encoding;

  public StringWriterWithEncoding (StringBuilder builder, Encoding encoding) :base(builder)
  {
    this.encoding = encoding;
  }

  public override Encoding Encoding
  {
    get { return encoding; }
  }
}

答案 1 :(得分:0)

为什么不使用已指定编码的XmlWriterXmlWriter需要基础流,但您只需给它一个MemoryStream

至于使用哪种编码,为什么不通过WebClient.Encoding? :

public static void PostXml(XmlDocument doc, String url)
{
    using (WebClient wc = new WebClient())
    {
        wc.UploadData(url, DocumentToData(doc, wc.Encoding));
    }
}

private static byte[] DocumentToData(XmlDocument doc, Encoding encoding)
{
    XmlWriterSettings settings = new XmlWriterSettings();
    settings.Encoding = encoding;
    settings.Indent = true;

    using (MemoryStream s = new System.IO.MemoryStream())
    {
        using (XmlWriter writer = XmlWriter.Create(s, settings))
        {
            doc.Save(writer);

            // You could make the return type string, but why make 
            // the web client round trip it back to bytes again?
            // return encoding.GetString(s.GetBuffer());

            return s.GetBuffer();
        }
    }
}

我还没有在真实的应用程序中对此进行过测试,所以如果我在这里遗漏了一些东西,请告诉我。