сериализация общих данных XML по запросам веб-службы WCF - PullRequest
4 голосов
/ 01 июня 2009

У меня есть веб-приложение, которое отправляет запрос в службу WCF. Служба WCF получает набор результатов LINQ (anon. Ilist) и отправляет его в ответ обратно в веб-приложение. Чтобы он работал быстро, в приложении WCF я использую copytodatatable и отправляю его в мое веб-приложение в DataSet.

Мое веб-приложение берет DataSet и записывает его в xml, выполняется xslt, и полученные данные отображаются на экране. Отлично. ... ну не совсем.

Я все еще (относительно) новичок в WCF. Я понимаю, что отправка DataTables / DataSets немного громоздка. Веб-приложению нужны данные в формате xml (для операции xslt), поэтому я решил, что веб-служба WCF заставит меня работать с DataTable -> xml и просто ответит хорошим XmlDocument клиентскому веб-приложению.
Однако XmlDocument не может быть сериализован.

Каков наилучший способ отправки данных XML клиенту через wcf?

  • Таблица данных содержит множество столбцов и будет довольно часто меняться, поэтому я не хочу создавать свой собственный объектный класс (с такими же свойствами, как у bazillion) и отправлять его (поскольку это то, что я сделал большую часть времени ранее в wcf он работал хорошо ... но не подходит для этого сценария).

  • РЕДАКТИРОВАТЬ : отправка в виде строки тоже работает .... но это, безусловно, не может быть лучшим решением?

Ответы [ 4 ]

5 голосов
/ 01 июня 2009

Единственная проблема при отправке наборов данных через WCF состоит в том, что он не совместим - то есть вы не сможете использовать набор данных из клиента, не являющегося .NET.

Я работал в нескольких крупных приложениях, которые отлично отправляют наборы данных по проводам через WCF. Пока отправитель и получатель работают в .NET, все будет в порядке.

Если вы по-прежнему не хотите использовать наборы данных, рассмотрите возможность создания класса DataContract для хранения данных для отправки по проводам. Это классический способ передачи данных через WCF. Если ваш XML не является достаточно сложным (что вполне может быть), это может быть хорошей альтернативой.

Если у вас его еще нет, я настоятельно рекомендую взять копию превосходного «Программирование служб WCF 2-го издания» Ювала Лоуи. У него есть целая глава о передаче информации через WCF. Это Библия WCF.

1 голос
/ 01 июня 2009

Вы можете просто вернуть XmlElement - возможно, свойство DocumentElement экземпляра XmlDocument.

Вам не нужно использовать XmlSerializer для этого . DataContractSerializer является значением по умолчанию и отправит обратно XmlElement очень хорошо. Вам не нужно реализовывать IXmlSerializable.

следующий пример кода

Сервисный интерфейс:

using System;
using System.Xml;
using System.ServiceModel;
using System.Runtime.Serialization;

namespace Cheeso.Samples.Webservices
{
    [ServiceContract(Namespace="urn:Cheeso.Samples" )]
    public interface IService
    {
        [OperationContract]
        XmlElement Register(String request);
    }
} 

Обратите внимание, у меня нет DataContract (и, следовательно, нет DataMembers), потому что я отправляю обратно экземпляр предопределенного класса (XmlElement).

Это реализация сервиса:

using System;
using System.Xml;
using System.ServiceModel;

namespace Cheeso.Samples.Webservices._2009Jun01
{

    public class Results
    {
        public int Id;
        public Int64 WorkingSet;
        public String Name;
        public String Title;
    }

    [ServiceBehavior(Name="WcfXmlElementService",
                     Namespace="urn:Cheeso.Samples",
                     IncludeExceptionDetailInFaults=true)]

    public class WcfXmlElementService : IService
    {
        int index = 0;
        public XmlElement Register(string request)
        {
            XmlDocument doc = new XmlDocument();

            // can get the doc from anywhere. We use a LINQ-to-Objects result.

       // do the LINQ thing
       var processInfo =
       from p in System.Diagnostics.Process.GetProcesses()
       select new Results {
           Id = p.Id,
           WorkingSet = p.WorkingSet64,
           Name = p.ProcessName,
           Title = p.MainWindowTitle
           };

       // Note: cannot use an anonymous ilist if we will use XmlSerializer

       // serialize that list into the XmlDocument
       using (XmlWriter writer = doc.CreateNavigator().AppendChild())
       {
       var L = processInfo.ToList();
       XmlSerializer s1 = new XmlSerializer(L.GetType());
       s1.Serialize(writer, L);
       }

       index++;

       // Append some additional elements to the in-memory document.
       XmlElement elem = doc.CreateElement("id");
       elem.InnerText = System.Guid.NewGuid().ToString();
       doc.DocumentElement.AppendChild(elem);

       elem = doc.CreateElement("stamp");
       elem.InnerText = DateTime.Now.ToString("G");
       doc.DocumentElement.AppendChild(elem);

       elem = doc.CreateElement("in-reply-to");
       elem.InnerText = request;
       doc.DocumentElement.AppendChild(elem);

            return doc.DocumentElement;
        }
    }
}

Клиент, если вы используете .NET, получает XmlElement. Если вы используете какой-либо другой стек, это будет просто XmlElement или XmlNode в этом стеке.

XSD для ответного сообщения является общим, как это:

<xs:element name="RegisterResponse">
  <xs:complexType>
    <xs:sequence>
      <xs:element minOccurs="0" name="RegisterResult" nillable="true">
        <xs:complexType>
          <xs:sequence>
            <xs:any minOccurs="0" processContents="lax" /> 
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
</xs:element>
0 голосов
/ 01 июня 2009

Класс, возвращаемый методом, должен реализовывать IXmlSerializable.

public XmlContent XmlContent()
{
    return new XmlContent();
}

[XmlRoot(ElementName = "div")]
public class XmlContent : IXmlSerializable
{

    #region IXmlSerializable Members

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        throw new NotImplementedException();
    }

    public void WriteXml(XmlWriter writer)
    {

    writer.WriteRaw("<p>some text</p>");

    }
    #endregion
}

Я до сих пор не нашел, как избежать сериализации корневого элемента (например, "div").

Я также пытался отправить XML в виде строки, но он не выводится, как ожидалось, то есть «строка» закодирована в HTML и заключена в теги. Это делает синтаксический анализ очень трудным.

0 голосов
/ 01 июня 2009

Почему бы вам не попробовать отправить xml в виде строки?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...