2010-06-04 50 views
1

我在過去用Delphi編寫過Web服務,但大部分都非常簡單,只需要一些參數並向客戶端返回一個值。我正在處理的一項新服務要求我能夠發送和接收復雜類型。請看下面的類型在我的代碼中定義:TRemotable Descendant父成員不包含在由delphi web服務生成的WSDL中

TBaseRequest = Class(TRemotable) 
    private 
    FUsername: string; 
    FPassword: string; 
    published 
    Property Username: String read FUsername write FUsername; 
    Property Password: String read FPassword write FPassword; 
End; 

TBaseResponse = Class(TRemotable) 
    private 
    FStatusMessage: string; 
    FStatusCode: integer; 
    published 
    Property StatusMessage: string read FStatusMessage write FStatusMessage; 
    Property StatusCode: integer read FStatusCode write FStatusCode; 
End; 

TSepecialRequest = class(TBaseRequest) 
private 
    FExtraParam: string; 
published 
    Property ExtraParam: String read FExtraParam write FExtraParam; 
end; 

TSpecialResponse = class(TBaseResponse) 
private 
    FExtraResult: string; 
published 
    Property ExtraResult: String read FExtraResultwrite FExtraResult; 
end; 

所有這些類都與RemClassRegistry.RegisterXSClass registerd。

現在我也得到了接口中定義此WebService如下功能:

function SpecialMethod(request:TSepecialRequest): TSpecialResponse; 

在服務代碼中,我可以很容易地訪問諸如用戶名和密碼的父類的屬性,但是如果我們看一下在生成的WSDL中,我們看到TSpecialRequest和TSpecialResponse類成員包含在模式部分中。

<xs:complexType name="TSpecialRequest"> 
    <xs:complexContent> 
     <xs:extension base="TBaseRequest"> 
     <xs:sequence> 
      <xs:element name="ExtraParam" type="xs:string"/> 
     </xs:sequence> 
     </xs:extension> 
    </xs:complexContent> 
    </xs:complexType> 
    <xs:complexType name="TSpecialResponse"> 
    <xs:complexContent> 
     <xs:extension base="TBaseResponse"> 
     <xs:sequence> 
      <xs:element name="ExtraResult" type="xs:string"/> 
     </xs:sequence> 
     </xs:extension> 
    </xs:complexContent> 
    </xs:complexType> 

在WSDL此模式片段表明TSpecials是TBASE類的一些推廣和一切都很好除了TBASE類的能解密中不包括的模式。我希望這裏也有一個這樣的部分,但它缺失:

<xs:complexType name="TBaseRequest"> 
    <xs:sequence> 
     <xs:element name="Username" type="xs:string"/> 
     <xs:element name="Password" type="xs:string"/> 
    </xs:sequence> 
    </xs:complexType> 
    <xs:complexType name="TBaseResponse"> 
    <xs:sequence> 
     <xs:element name="StatusMessage" type="xs:string"/> 
     <xs:element name="StatusCode" type="xs:int"/> 
    </xs:sequence> 
    </xs:complexType> 

但是,這個模式片段從生成的WSDL中缺少。這意味着任何嘗試使用此服務的客戶端將無法正確生成請求或解釋響應。例如,如果我試圖將geneated WSDL裝入WSDL進口商德爾福2009年,我得到了以下類:

TSpecialRequest = class(TRemotable) 
private 
    FExtraParam: WideString; 
published 
    property ExtraParam: WideString read FExtraParam write FExtraParam; 
end; 

TSpecialResponse = class(TRemotable) 
private 
    FStatusMessage: WideString; 
    FStatusCode: Integer; 
published 
    property StatusMessag: WideString read FStatusMessage write FStatusMessage; 
    property StatusCode: Integer read FStatusCode write FStatusCode; 
end; 

的結果是,客戶端代碼是不能做的事情一樣設定的用戶名和密碼成員應該是TSpecialRequest的一部分。

有沒有人有任何線索爲什麼會發生這種情況,或者我可以做些什麼?

+0

如何使用Delphi IDE從Delphi類源代碼創建WSDL?直到現在我還沒有看到用Delphi 2009 Enterprise做這件事的方法(也許我應該讓它成爲一個新的SO問題:) – mjn 2010-06-04 17:42:15

+0

它的離題和應該是一個新問題,但基本上當你創建一個SOAP服務器應用程序項目時將在其上添加一個TWSDLHTMLPublish組件的數據模塊。這個組件通過註冊的接口和遠程類,並添加生成一個WSDL。要訪問WSDL,必須將項目的已編譯DLL加載到ISAPI Web服務器(如IIS)中,然後使用URL(如http://server.com/project.dll),您將看到一個描述該服務的HTML頁面和鏈接到生成的WSDL。結果:基於在delphi代碼中定義的類的WSDL。 – 2010-06-05 21:09:22

回答

1

我不認爲我會得到答案,但我找到了解決辦法。我並沒有真正滿足它,但它讓我通過了這個問題。上述症狀可以通過使用Object Composition而不是繼承來避免。此代碼按預期運行,但不易使用。我想我會想在我的執行過程中想出一些消息工廠,但那是下主題。

該溶液可以通過下面的代碼來說明:

TBaseRequest = Class(TRemotable) 
    private 
    FUsername: string; 
    FPassword: string; 
    published 
    Property Username: String read FUsername write FUsername; 
    Property Password: String read FPassword write FPassword; 
end; 

TSepecialRequest = class(TRemotable) 
private 
    FExtraParam: string; 
    FBaseRequest: TBaseRequest; 
published 
    Property ExtraParam: String read FExtraParam write FExtraParam; 
    Property BaseRequest: TBaseRequest read FBaseRequest write FBaseRequest; 
end; 
1

的Delphi僅生成用於在Web服務的接口直接引用類的模式。理想情況下,它應該包含基類返回TRemotable,但它不。我發現,如果你在參數列表中添加一個虛擬方法到你的基類中,Delphi會產生缺失的定義。例如:

procedure BaseClasses(BaseRequest: TBaseRequest; BaseResponse: TBaseResponse); stdcall; 

這絕對是一個黑客,這是一個有點討厭不得不公開這樣的方法,但它並完成你想要做的事情。

我知道這個迴應對你來說有點遲,但也許對其他人來說很有用。

相關問題