2010-04-20 25 views
1

我有一個WSDL,我的web服務的消費者期望會嚴格遵守。我將它轉換爲wsdl.exe的接口,並讓我的web服務實現它。除了這個問題,我對結果普遍滿意。如何使用從wsdl自動生成的類重寫C#DateTime序列化?

一個簡單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. 在那之後,我想,我會砍了生成的代碼太多我喜歡並不斷尋找其他解決方案。

+0

你不應該,在一般情況,得到那個例外。你可以顯示你的'IXmlSerializable'實現嗎? – 2010-04-21 00:50:55

回答

0

我是個白癡!

首先,正則表達式的意思是「數字之間1和7」不是「1個或7位數」,但在我的防守,the internet是錯誤的。響應沒有驗證的原因是,它缺少的「Z」結尾表示UTC。

的解決方案是如此簡單:

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

而且它的工作本身了!

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

我從來沒有見過WSDL中的XML Schema對xsd:dateTime設置了限制。

我相信你必須在你的GetCurrentTimeResponse課上實施IXmlSerializable。你可以這樣做,因爲C#的「部分類」功能。在您的項目中創建另一個文件並添加以下代碼:

public partial class GetCurrentTimeResponse : 
    System.Xml.Serialization.IXmlSerializable 
{ 
    public XmlSchema GetSchema() { return null; } 

    public void ReadXml(XmlReader reader) { 
     // Fill the TimeStamp property here 
    } 

    public void WriteXml(XmlWriter writer) { 
     // Write out TimeStamp.ToString(
     // System.Globalization.CultureInfo.InvariantCulture, 
     // "proper format"); 
    } 
} 
+0

反應良好,謝謝大家。請參閱已編輯的問題以瞭解更多關於我嘗試此方法時發生的情況此外,請參閱我的回答關於爲什麼XSD好像把一個限制的日期時間類型的新見解。 – 2010-04-20 22:10:27

1

可能不是最相關的答案,你原來的問題,但因爲我得到了重定向到這個頁面,同時尋找一種方式來控制序列化別人的DateTime屬性的格式可能會發現它很有用。

我發現,通過添加以下到您的app.config/web.config中指示.net序列一致格式化的DateTime屬性:

<system.xml.serialization> 
    <dateTimeSerialization mode="Local" /> 
    </system.xml.serialization> 

編號:http://msdn.microsoft.com/en-us/library/ms229751(v=VS.85).aspx