2009-06-01 170 views
4

我有一个Web应用程序向WCF服务发送请求。 WCF服务获得一个LINQ结果集(匿名。ilist)并将其发送回Web应用程序。 为了让它快速工作,在WCF应用程序内部,我使用了copytodatatable并将它发送到我的Web应用程序的DataSet中。通过WCF Web服务请求序列化通用XML数据

我的网络应用程序然后将DataSet写入到xml中,执行一些xslt,并在屏幕上显示结果数据。完善。 ...呃,不是真的。

我还是(相对)新的WCF。我明白发送DataTables/DataSets有点麻烦。 Web应用程序需要xml格式的数据(用于xslt操作),所以我想我会得到WCF Web服务来为我做DataTable - > xml工作,并简单地向客户端webapp回复一个很好的XmlDocument。
但是,无法序列化XmlDocument。

通过wcf将XML数据发送到客户端的最佳方式是什么?

  • DataTable中含有大量的字段,并且将相当freqently所以我不希望创建自己的对象类改变(与像bazillion属性),并发送(因为这是我以前在wcf中大部分时间都完成了,它运行良好......但不适合这种情况)。

  • 编辑:发送下来作为一个字符串的作品太....但是这肯定不能成为最好的解决

回答

5

通过WCF发送数据集的唯一问题是它不能互操作 - 即无法使用非.NET客户端的数据集。

我曾经在几个大型应用程序中通过WCF发送数据集通过WCF很好。只要发送者和接收者都在.NET上运行,你应该没问题。

如果您仍然不想使用数据集,那么可以考虑创建一个DataContract类来保存要通过线路发送的数据。这是通过WCF传输数据的经典方式。除非你的XML非常复杂(很可能),否则这可能是一个好的选择。

如果你还没有,我强烈建议你拿一份Juval Lowy出色的“Programming WCF Services 2nd Edition”的副本。他有关于通过WCF传输信息的整章。这是WCF圣经。

+0

我有这本书在我面前...;) 把它从我的同事办公桌上删除... 感谢您的提示。 – GordonB 2009-06-01 15:06:34

-1

你为什么不尝试发送xml作为字符串?

+0

发生在我身上,但我只是认为,因为数据是XML,是一个XmlDocument将是最好的数据类型.. ..我已经尝试了一些可以工作的数据类型,并且我的应用程序确实有效。我只是在寻找最好的,最好的做法。 – GordonB 2009-06-01 14:44:37

0

该方法返回的类需要实现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编码并包装在标记中。这使解析非常困难。

1

您可以简单地返回一个XmlElement - 可能是一个XmlDocument实例的DocumentElement属性。

您不必use the XmlSerializer to do this。 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(并且因此没有数据成员),因为我发回一个预定义的类(的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>