Сохранять пробелы / разрывы строк при сериализации через веб-службу ASMX

Я делаю некоторую предварительную обработку документа XML в веб-службе ASMX (устаревшая служба .NET SOAP) для возможного использования в интерфейсе Silverlight.

Я обрабатываю этот XML-документ в виде объекта POCO для простоты использования. Объект определяется следующим образом:

public class CACDocument : ITextDocument
{
    #region Properties
    public string Title { get; set; }
    public string Text { get; set; }
    public List<Code> CodeList { get; set; }
    public XElement FormatedText { get; set; }
    #endregion

    #region Constructor
    public CACDocument()
    {
        CodeList = new List<Code>();
    }
    #endregion
}

Свойство Text в этом объекте содержит в основном форматированный текст (разрывы строк, пробелы и т. Д.). Узел XML, который передает это свойство, выглядит следующим образом:

<text>
   A TITLE FOLLOWED BY two line breaks


   Some text followed by a line break

   Some more text that might extend for a paragraph or two followed by more line breaks

   Still more text
</text>

Все в порядке, и формат поддерживается, как и следовало ожидать, пока веб-службы не сериализуют данные, которые будут отправлены во внешний интерфейс. Я предполагаю, что при попытке оптимизировать пропускную способность сериализованный объект удаляет лишние пробелы и разрывы строки из свойства Text перед отправкой. В этом конкретном случае это форматирование важно. Есть ли способ заставить веб-сервис поддерживать форматирование пробелов и разрывов строк?

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

Ответы на вопрос(2)

Решение Вопроса

Вы можете сериализовать его как раздел CDATA:

    [XmlIgnore]
    public string Text { get; set; }

    private static readonly XmlDocument _xmlDoc = new XmlDocument();

    [XmlElement("Text")]
    public XmlCDataSection TextCData
    {
        get
        {
            return _xmlDoc.CreateCDataSection(Text);
        }
        set
        {
            Text = value.Data;
        }
    }

Текст будет сериализован так:

<text><![CDATA[A TITLE FOLLOWED BY two line breaks


   Some text followed by a line break

   Some more text that might extend for a paragraph or two followed by more line breaks

   Still more text]]></text>
 John Saunders09 июл. 2009 г., 15:42
Как влияют все эти разделы CData, прикрепленные к документу? И это потокобезопасно?
 Thomas Levesque09 июл. 2009 г., 16:28
Честно говоря, я понятия не имею ... может, вместо этого XmlDocument должен быть локальной переменной, я просто хотел избежать создания многих экземпляров XmlDocument.

На самом деле, я не думаю, что есть способ сделать это без сериализации в виде байтового массива. В качестве альтернативы, вы можете реализовать IXmlSerializable и делать всю работу самостоятельно.

Тебе захочется что-то вроде этого:

public class CACDocument : ITextDocument {
    // ...
    [XmlIgnore]
    public string Text {get;set;}

    [XmlText]
    public byte[] TextSubstitute {
        get {return System.Text.Encoding.UTF8.GetBytes(Text);}
        set {Text = System.Text.Encoding.UTF8.GetString(value);}
    }
}

Это не проверено, но ты поймешь. Вы также можете использовать [XmlElement] вместо [XmlText] и указать другое имя элемента.

 Steve Brouillard09 июл. 2009 г., 15:11
Ты прав в своем предположении. Итак, вы говорите, что мне нужно преобразовать свойство строки в свойство байтового массива, или есть особая настройка, которая позволит мне явно сериализовать строку как байтовый массив?
 John Saunders09 июл. 2009 г., 19:52
Стив, мне любопытно - ты пробовал решение Томаса CDATA ниже? У меня нет шансов попробовать.
 Steve Brouillard10 июл. 2009 г., 13:58
Я вчера попал на встречи. Я собираюсь попробовать его решение сегодня и прокомментирую его позже.
 Steve Brouillard10 июл. 2009 г., 16:39
John. Я попробовал решение CDATA Томаса ниже, и оно работает как шарм. Я не знаю о безопасности потоков, но для моих целей это не актуально. В любом случае, когда этот процесс будет использоваться, это будет один вызов веб-службы, и результаты будут обработаны в локальные объекты POCO, и, поскольку в любом случае это Silverlight и async, мне нужно вызвать событие, когда процесс завершен, поэтому нет никакой возможности получить доступ к объекту из другого потока до этого времени. Он также имеет дополнительное преимущество ограничения данных, передаваемых по проводам.

Ваш ответ на вопрос