【问题标题】:.NET: Posting Xml to a web-server?.NET:将 Xml 发布到 Web 服务器?
【发布时间】:2011-04-22 12:00:14
【问题描述】:

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 的问题在于它按原样发布字符串完全。这意味着(在我的情况下)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 post需要正确编码,这通常发生在调用:

Save(textWriter)

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

另见

【问题讨论】:

    标签: .net xml xml-serialization xmlhttprequest


    【解决方案1】:

    这是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; }
      }
    }
    

    【讨论】:

    • 那家伙故意弄乱字符串,然后想知道为什么字符串无效。在他包含的链接之后,其中一位响应者是正确的,他说:“为什么需要 UTF-8 编码的字符串?内存中的字符串是 unicode (UTF-16);我不知道还有其他方法可以制作它们是 UTF-8,而不会将它们写入文件或内存流。” String UTF-16,试图将UTF-8字节填充到其中是完全无效的。
    【解决方案2】:

    为什么不使用您已为其指定编码的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();
            }
        }
    }
    

    我没有在实际应用程序中对此进行测试,所以如果我在这里遗漏了什么,请告诉我。

    【讨论】:

      猜你喜欢
      • 2011-01-19
      • 2015-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-04
      • 1970-01-01
      • 2013-02-04
      • 1970-01-01
      相关资源
      最近更新 更多