【发布时间】:2010-04-20 20:06:51
【问题描述】:
我有一个 WSDL,我的 Web 服务的使用者希望严格遵守该 WSDL。我将它转换为带有 wsdl.exe 的接口,并让我的 Web 服务实现它。除了这个问题,我对结果总体上很满意。
一个简单的 GetCurrentTime 方法将具有从接口定义中的 WSDL 生成的以下响应类:
[System.CodeDobmCompiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="[Client Namespace]")]
public partial class GetCurrentTimeResponse {
private System.DateTime timeStampField;
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified]
public System.DateTime TimeStamp{
// [accesses timeStampField]
}
}
当我将响应数据放入自动生成的响应类时,它会被序列化为适当的 XML 响应。 (大多数 Web 方法的返回类型要复杂得多,具有多级数组。)
问题在于 DateTime 对象的默认序列化违反了 WSDL 中的要求之一:
...
<xsd:simpleType name="SearchTimeStamp">
<xsd:restriction base="xsd:dateTime">
<xsd:pattern value="[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(.[0-9]{1,7})?Z">
</xsd:restriction>
</xsd:simpleType>
...
注意模式的最后一部分,如果包含亚秒,则亚秒必须是 1 或 7 个字符。客户端似乎拒绝响应,因为它不符合该要求。
主要问题是,当 .NET 序列化 DateTime 对象时,它会省略所有尾随零,这意味着生成的亚秒值的长度会有所不同。 (例如,“12:34:56.700”默认序列化为“<TimeStamp>12:34:56:7</TimeStamp>”)。我们使用毫秒精度,因此我需要将所有时间戳格式化为 7 个亚秒数字,以符合 WSDL。
如果我可以指定格式字符串会很容易,但我不确定如何控制 DateTime 对象用于序列化为 XML 的字符串,或者以其他方式覆盖序列化行为。我该怎么做呢?请记住以下几点...
- 我想尽可能少地修改生成的代码...如果可以通过部分类或继承类进行更改,最好根本不修改。
- 使用继承类作为 Web 方法的返回类型将导致 Web 服务不再实现自动生成的接口。
- TimeStamp 类型出现在其他更复杂的响应类型中。因此,手动覆盖整个序列化过程可能非常耗时。
更新:
正如约翰建议的那样,我在早期尝试实现 IXmlSerializable ,但出现以下错误:
System.InvalidOperationException: There was an error reflecting type '[...].GetCurrentTimeResponse'. ---> System.InvalidOperationException: Only XmlRoot attribute may be specified for the type [...].GetCurrentTimeResponse. Please use XmlSchemaProviderAttribute to specify schema type.
在那之后,我认为我不得不根据自己的喜好对生成的代码进行过多的修改,并继续寻找其他解决方案。
【问题讨论】:
-
一般来说,你不应该得到那个例外。你能展示你的
IXmlSerializable实现吗?
标签: c# .net web-services datetime wsdl