.NET: Размещение Xml на веб-сервере? - PullRequest
2 голосов
/ 07 октября 2010

Как правильно разместить 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.


HTTP-пост XML должен быть правильно закодирован, что обычнопроисходит во время вызова:

Save(textWriter)

Во время вызова Save объект XmlDocument будет корректировать объявление xml на основе Encoding из TextWriter, в котором его просят сохранить.К сожалению, WebClient не предоставляет TextWriter, который я могу сохранить в XmlDocument.

См. Также

Ответы [ 2 ]

0 голосов
/ 15 марта 2011

Почему бы не использовать XmlWriter, для которого вы указали кодировку.XmlWriter требует базового потока, но вы можете просто дать ему 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();
        }
    }
}

Я не проверял это в реальном приложении, поэтому дайте мне знать, если я что-то здесь упускаю.

0 голосов
/ 07 октября 2010

Это решение .Подкласс 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; }
  }
}
...