跨 WCF Web 服务请求序列化通用 XML 数据
Posted
技术标签:
【中文标题】跨 WCF Web 服务请求序列化通用 XML 数据【英文标题】:serializing generic XML data across WCF web service requests 【发布时间】:2010-10-30 10:08:36 【问题描述】:我有一个向 WCF 服务发送请求的 Web 应用程序。 WCF 服务获取一个 LINQ 结果集(anon.ilist)并将其作为回复发送回 Web 应用程序。 为了让它快速运行,在 WCF 应用程序中,我使用 copytodatatable 并将其发送到 DataSet 中的我的网络应用程序。
然后,我的 Web 应用程序获取 DataSet 并将其写入 xml,执行一些 xslt 并将结果数据显示在屏幕上。完美的。 ...嗯,不是真的。
我还是(相对)WCF 新手。我知道发送 DataTables/DataSets 有点麻烦。 Web 应用程序需要 xml 格式的数据(用于 xslt 操作),所以我想我会让 WCF Web 服务为我完成 DataTable -> xml 工作,然后简单地用一个漂亮的 XmlDocument 回复客户端 webapp。 但是不能序列化 XmlDocument。
通过 wcf 将 XML 数据发送到客户端的最佳方式是什么?
数据表包含很多列,并且会经常更改,所以我不想创建自己的对象类(具有无数属性)并发送它(因为这是我所做的以前在 wcf 中的大部分时间,它运行良好......但不适合这种情况)。
编辑:将其作为字符串发送也可以....但这肯定不是最佳解决方案吗?
【问题讨论】:
【参考方案1】:通过 WCF 发送数据集的唯一问题是它不可互操作 - 即您无法从非 .NET 客户端使用数据集。
我在几个大型应用程序中工作过,这些应用程序通过 WCF 通过网络发送数据集就很好。只要发送方和接收方都在 .NET 上运行,您应该没问题。
如果您仍然不想使用数据集,请考虑创建一个 DataContract 类来保存您的数据以通过网络发送。这是跨 WCF 传输数据的经典方式。除非您的 XML 非常复杂(很可能是这样),否则这可能是一个不错的选择。
如果您还没有,我强烈建议您阅读 Juval Lowy 出色的“Programming WCF Services 2nd Edition”的副本。他有一整章是关于跨 WCF 传输信息的。这是 WCF 圣经。
【讨论】:
这本书在我面前... :) 这是一本超级密集的书。我建议把第 1 章读几遍,尽管我认为第 3 章是你感兴趣的。不过,不要把我的副本放在我面前。 :)【参考方案2】:您可以简单地返回一个 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(因此也没有 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>
【讨论】:
【参考方案3】:方法返回的类需要实现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 编码并包装在标签中。这使得解析非常困难。
【讨论】:
【参考方案4】:为什么不尝试将 xml 作为字符串发送?
【讨论】:
发生在我身上,但我只是假设由于数据是 xml,所以 xmldocument 将是最好的数据类型....我已经尝试了几种数据类型工作,我的应用程序确实工作。我只是在寻找最好的、最佳实践的方法。以上是关于跨 WCF Web 服务请求序列化通用 XML 数据的主要内容,如果未能解决你的问题,请参考以下文章
C# 中 WCF 和 MVC Web API 的通用请求响应拦截器
C# Restful WCF 服务。无法在帖子正文中反序列化 XML