使用 XmlSerializer 类
Windows Communication Foundation (WCF) 可以使用两种不同的序列化技术将应用程序中的数据转换为在客户端和服务之间进行传输的 XML,此过程称为序列化。
DataContractSerializer 为默认序列化程序
默认情况下,WCF 使用 DataContractSerializer 类来序列化数据类型。此序列化程序支持下列类型:
- 基元类型(如:整数、字符串和字节数组)以及某些特殊类型(如 XmlElement 和 DateTime),这些特殊类型也被视为基元类型。
- 数据协定类型(用 DataContractAttribute 属性标记的类型)。
- 用 SerializableAttribute 属性标记的类型,包括实现 ISerializable 接口的类型。
- 实现 IXmlSerializable 接口的类型。
- 许多常见集合类型,包括许多泛型集合类型。
许多 .NET Framework 类型属于后两种类别,因此可序列化。可序列化类型的数组也可序列化。有关完整列表,请参见在服务协定中指定数据传输。
与数据协定类型一起使用的 DataContractSerializer,是编写新 WCF 服务的推荐方式。有关更多信息,请参见 使用数据协定。
使用 XmlSerializer 类的时机
WCF 还支持 XmlSerializer 类。XmlSerializer 类不是 WCF 的专用类。ASP.NET Web 服务同样使用该类作为序列化引擎。XmlSerializer 类支持的类型少于 DataContractSerializer 类支持的类型,但它允许对生成的 XML 进行更多的控制,并且支持更多的 XML 架构定义语言 (XSD) 标准。它也不需要在可序列化类型上有任何声明性属性。有关更多信息,请参见 .NET Framework 文档中的 XML 序列化主题。XmlSerializer 类并不支持数据协定类型。
使用 Svcutil.exe 或 Visual Studio 中的“添加服务引用”功能来生成第三方服务的客户端代码或访问第三方架构时,系统会自动为您选择一个合适的序列化程序。如果架构与 DataContractSerializer 不兼容,则选择 XmlSerializer。
手动切换到 XmlSerializer
有时候,您也许必须手动切换到 XmlSerializer。例如,在以下情况下可能需要这样做:
- 将应用程序从 ASP.NET Web 服务迁移到 WCF 时,您可能需要重用现有的、与 XmlSerializer 兼容的类型,而不是创建新的数据协定类型。
- 当对出现在消息中的 XML 的精确控制很重要,而 Web 服务描述语言 (WSDL) 文档不可用时,例如,在使用必须遵循某个已标准化且已发布的架构(与 DataContractSerializer 不兼容)的类型来创建服务时。
- 创建遵循旧式 SOAP 编码标准的服务时。
在这些情况和其他情况下,您可以通过将 XmlSerializerFormatAttribute 属性应用于您的服务来手动切换到 XmlSerializer 类,如以下代码所示。
安全注意事项
提示
切换序列化引擎时需要小心,这一点非常重要。根据所使用的序列化程序,相同的类型可以序列化为不同的 XML。如果意外使用了错误的序列化程序,则可能会公开类型中您不希望公开的信息。
例如,在序列化数据协定类型时,DataContractSerializer 类只序列化用 DataMemberAttribute 属性标记的成员。XmlSerializer 类序列化任何公共成员。请看以下代码中的类型。
如果在选择了 XmlSerializer 类的服务协定中不慎使用了该类型,则将序列化 creditCardNumber
成员,这可能并不是想要的结果。
即使 DataContractSerializer 类为默认值,您也可以通过将 DataContractFormatAttribute 属性应用于服务协定类型来为您的服务显式选择此类(虽然从不要求进行此项操作)。
用于服务的序列化程序是协定的不可分割的一部分,您无法通过选择不同的绑定或更改其他配置设置来对其进行更改。
此外,在使用 XmlSerializer 类时还需注意以下重要安全事项。首先,强烈建议对任何使用 XmlSerializer 类的 WCF 应用程序使用确保不会泄漏的密钥来进行签名。在执行手动切换到 XmlSerializer 和执行自动切换(通过 Svcutil.exe、添加服务引用或类似工具)时都适合采用此建议。这是由于 XmlSerializer 序列化引擎支持预生成的序列化程序集**的加载,只要这些程序集使用与应用程序相同的密钥进行签名。如果某恶意程序集的名称与放置在应用程序文件夹或全局程序集缓存中的预生成序列化程序集的预期名称相匹配,则未签名的应用程序对于此类恶意程序集的攻击完全没有防御能力。当然,攻击者必须首先获取对这两个位置中某个位置的写权限才能尝试进行攻击。
您使用 XmlSerializer 时存在的另一个威胁与系统临时文件夹的写权限有关。XmlSerializer 序列化引擎创建并使用此文件夹中的临时序列化程序集**。您应该注意,任何对临时文件夹具有写权限的进程都可能用恶意代码覆盖这些序列化程序集。
XmlSerializer 支持的规则
您不能直接将与兼容 XmlSerializer 的属性应用于协定操作参数或返回值。但是,可将这些属性应用于类型化消息(消息协定正文部分),如以下代码所示。
当应用于类型化消息成员时,这些属性 (Attribute) 将覆盖与类型化消息属性 (Attribute) 相冲突的属性 (Property)。例如,在下列代码中,ElementName
覆盖 Name
。
使用 XmlSerializer 时不支持 MessageHeaderArrayAttribute 属性。
提示
在这种情况下,XmlSerializer 引发下面的异常,该异常在 WCF 之前发布:“在架构的顶级声明的元素的 maxOccurs 不能大于 1。使用 XmlArray 或 XmlArrayItem 而不是 XmlElementAttribute,或使用换行的参数样式为‘more’提供包装元素”。
如果您接收到此异常,请调查是否属于这种情况。WCF 并不支持消息协定和操作协定中的 SoapIncludeAttribute 和 XmlIncludeAttribute 属性;请改用 KnownTypeAttribute 属性。
另请参见
任务
如何:使用 XmlSerializer 改善 WCF 客户端应用程序的启动时间
参考
DataContractFormatAttribute
DataContractSerializer
XmlSerializer
MessageHeaderArrayAttribute