2008-12-01 22 views
1

過去,我需要在使用導入的WSDL Web引用的C#項目中創建自定義SOAP頭文件。我找到了一種方法來做到這一點,但我從來沒有滿意,我有理由懷疑是否有更好的方法。我所做的就是創建一個從SOAPHEADER派生的標題:是否有更好的方式來定製C#中的SOAP頭文件?

[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://model.test.net")] 
[System.Xml.Serialization.XmlRootAttribute("securitytoken", Namespace = "http://model.test.net", IsNullable = false)] 
public class SpecialHeader : SoapHeader 
{ 
    [System.Xml.Serialization.XmlTextAttribute()] 
    public string aheadervalue; 
} 

我只好再修改從WSDL生成的代碼和 CE添加一個參照的文新報頭的實例和每個前下網絡呼叫 我想包含自定義標題:

[System.Web.Services.Protocols.SoapHeaderAttribute("instancename", Direction=System.Web.Services.Protocols.SoapHeaderDirection.InOut)] 

其中「實例名稱」是自定義頁眉的實例變量名在生成的類。

這可以很好地工作,除了WSDL中的任何更改都要求將它全部重新完成,因爲它會重新生成類。在其他語言中,頭文件可以添加到生成的代碼之外,所以也許我錯過了在C#中完成的方式。有沒有更好的方法來做到這一點?

回答

0

有一種方法可以做到這一點,它不一定非常漂亮,並且在一個非常簡單的Web服務上它可能不值得這樣做,但它至少可以讓您不必在重新生成代碼時重新添加屬性。

由於發電機產生子類,您可以:

  1. 添加文件到您的項目與另一個「部分」部分(即,使用擴展了Web服務類(一個從SoapHttpClientProtocol衍生)與生成的類相同的名稱空間和名稱,並將其標記爲「部分」)。

  2. 將您想添加標題的方法複製到生成的代碼中(即,您已經添加屬性的相同方法)並將其粘貼到擴展部分。

  3. 稍微重命名這些方法,以便它們不會與生成的代碼中的方法發生衝突,並將傳遞給Invoke的名稱更改爲匹配。 (您可能還必須調整方法上的其他屬性,以確保它們仍映射到WSDL中的正確調用。)

  4. 將自定義標頭屬性添加到重命名的方法,並將標題實例字段添加到您的擴展部分。

  5. 從您的代碼中調用重命名的版本而不是原始版本。

只要方法簽名在WSDL中不發生更改,即使重新生成,也不必更改代碼中的任何內容。 (因爲您只複製相對較短的方法實現,所以WSDL中的任何其他結構仍然會從生成的代碼中提取出來,所以如果它們發生更改,則在重新生成時會自動獲取更新後的版本。在其中有任何其他結構,這可能是有限的)

它仍然不是理想的,但試圖攔截原始的XML消息,並將標題直接放入(你可能會做,但這將是討厭的),沒有任何其他選項我知道(無論如何不移動到WCF)。

3

看來你正在使用。Net 2.0和asmx Web服務。 您是否知道.Net 3.0中有一個名爲WCF(Windows Communication Framework)的框架。 我知道遷移到新的框架並不容易,但是使用WCF你會獲得如此多的收益。此外WCf可以用於遠遠超過WebServices(遠程處理,msmq和更多)。這是微軟未來投注的框架。 也就是說。使用MessageContracts完成肥皂頭的操作。

所以答案是,在WCF中你可以用MessageContracts做到這一點。

+0

@khebbie:我是WCF的新手,並嘗試設置自定義標題。消息合同聽起來像是要走的路。你知道一個很好的資源,我可以在這裏讀到嗎? – Adam 2010-04-05 21:50:12

0

今天我遇到了這個問題。我最終創建了一個從自動生成的類派生的類,並覆蓋了GetWriterForMessage方法,以確保我的頭文件始終存在。我會在每次調用方法時更新標題值。

2

生成的類別是部分類別。您可以在具有相同名稱空間和類名的另一個文件(再次部分類)上定義它。然後你可以覆蓋它的虛擬方法並定義一次。

這樣可以防止重新生成的類的進一步更改不會影響您編寫的類。

在新的類文件上,您可以使用「GetWriterForMessage」覆蓋並向其中添加新的SOAP標題。

public partial class SampleService 
{ 
    public string MessageID { get; set; } 

    protected override System.Xml.XmlWriter GetWriterForMessage(System.Web.Services.Protocols.SoapClientMessage message, int bufferSize) 
    { 
     message.Headers.Add(new UsernameSoapHeader("Username")); 
     message.Headers.Add(new PasswordSoapHeader("Password")); 
     message.Headers.Add(new MessageIDSoapHeader(MessageID)); 
     return base.GetWriterForMessage(message, bufferSize); 
    } 
} 
相關問題