如何使用从wsdl自动生成的类覆盖C#DateTime序列化? [英] How to override C# DateTime serialization with class auto-generated from wsdl?

查看:44
本文介绍了如何使用从wsdl自动生成的类覆盖C#DateTime序列化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Web服务使用者希望严格遵守的WSDL.我将它转换为与wsdl.exe的接口,并让我的Web服务实现了它.除了这个问题,我对结果总体上感到满意.

I have a WSDL that the consumer of my web service expects will be adhered to strictly. I converted it into an interface with wsdl.exe and had my web service implement it. Except for this problem, I have been generally pleased with the results.

一个简单的GetCurrentTime方法将在接口定义中具有从WSDL生成的以下响应类:

A simple GetCurrentTime method will have the following response class generated from the WSDL in the interface definition:

[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方法的返回类型要复杂得多,具有多个数组级别.)

When I put the response data into the automatically generated response class, it gets serialized into an appropriate XML response. (Most of the web methods have much more complicated return types with multiple levels of arrays.)

问题在于DateTime对象的默认序列化违反了WSDL中的要求之一:

The problem is that the default serialization of DateTime objects violates one of the requirements in the 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个字符.客户似乎拒绝了响应,因为它不符合该要求.

Note the last part of the pattern where subseconds must be either 1 or 7 characters if they are included. The client seems to be rejecting the response because it does not match that requirement.

主要问题是,当.NET序列化DateTime对象时,它将忽略所有结尾的零,这意味着所得的亚秒值的长度会有所不同.(例如,默认情况下,"12:34:56.700"被序列化为"< TimeStamp> 12:34:56:7 </TimeStamp> ").我们使用毫秒级的精度,因此我需要所有时间戳都必须以7亚秒数字进行格式化,以便与WSDL兼容.

The main issue is that when .NET serializes a DateTime object, it omits all trailing zeroes, meaning the resulting subsecond value varies in length. (e.g., "12:34:56.700" gets serialized as "<TimeStamp>12:34:56:7</TimeStamp>" by default). We use millisecond precision, so I need all timestamps to format with 7 subsecond digits in order to be compliant with the WSDL.

如果我可以指定格式字符串,那会很容易,但是我不确定如何控制DateTime对象用于序列化为XML或以其他方式覆盖序列化行为的字符串.我该怎么做呢?请记住以下内容...

It would be easy if I could specify a format string, but I'm not sure how to control the string that the DateTime object uses to serialize to XML, or to otherwise override the serialization behavior. How do I do this? Keeping in mind the following...

  • 我想尽可能少地修改生成的代码...如果可以通过部分类或继承的类进行更改,则最好根本不修改.
  • 使用继承的类作为web方法的返回类型将导致Web服务不再实现自动生成的接口.
  • TimeStamp类型出现在其他更复杂的响应类型中.因此,手动覆盖整个序列化过程可能会非常耗时.

更新:正如约翰建议的那样,我尝试尽早实现IXmlSerializable,并收到以下错误: System.InvalidOperationException:出现错误,反映了类型'[...].GetCurrentTimeResponse'.--->System.InvalidOperationException:只能为类型[...].GetCurrentTimeResponse指定XmlRoot属性.请使用XmlSchemaProviderAttribute指定架构类型.在那之后,我认为我将不得不过多地修改生成的代码,并继续寻找其他解决方案.

Update: I tried implementing IXmlSerializable early on, as John suggested, and got the following error: 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. After that, I figured that I would have to hack up the generated code too much for my liking and kept searching for other solutions.

推荐答案

我是个白痴!

首先,正则表达式的意思是"1到7位之间"而不是"1或7位之间",尽管在我的辩护中,互联网是错误的.响应未通过验证的原因是,它在末尾缺少表示UTC的"Z".

First, the regular expression means "between 1 and 7 digits" not "1 or 7 digits" although in my defense, the internet was wrong. The reason the response wasn't validating was that it was missing the "Z" at the end indicating UTC.

解决方案很简单:

GetCurrentTimeResponse response = new GetCurrentTimeResponse() {
    TimeStamp = timeStampWeWant.ToUniversalTime()
}

它成功了!

<TimeStamp>2010-04-20T20:12:16.674Z</TimeStamp>

这篇关于如何使用从wsdl自动生成的类覆盖C#DateTime序列化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆