簡體   English   中英

如何使用Delphi 2007中的非IIS托管,WCF,C#Web服務?

[英]How to consume non-IIS hosted, WCF, C# web service from Delphi 2007?

我編寫了一個相當簡單的小型C#Web服務,通​​過WCF從獨立的EXE托管。 代碼 - 有點簡化 - 看起來像這樣:

namespace VMProvisionEXE
{
class EXEWrapper
{
    static void Main(string[] args)
    {
        WSHttpBinding myBinding = new WSHttpBinding();
        myBinding.Security.Mode = SecurityMode.None;

        Uri baseAddress = new Uri("http://bernard3:8000/VMWareProvisioning/Service");
        ServiceHost selfHost = new ServiceHost(typeof(VMPService), baseAddress);

        try
        {
            selfHost.AddServiceEndpoint(typeof(IVMProvisionCore), myBinding, "CoreServices");

            ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
            smb.HttpGetEnabled = true;
            smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy12;
            selfHost.Description.Behaviors.Add(smb);

            // Add MEX endpoint
            selfHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");

            selfHost.Open();
            Console.WriteLine("The service is ready.");
            Console.ReadLine();

其余的C#代碼; 上面的類VMPService實現了VMProvisionCore.IVMProvisionCore。

namespace VMProvisionCore
{
[ServiceContract(Namespace = "http://Cisco.VMProvision.Core", ProtectionLevel = System.Net.Security.ProtectionLevel.None)]
public interface IVMProvisionCore
{
    [OperationContract]
    bool AuthenticateUser(string username, string password);
}

我可以輕松地創建使用此服務的Visual Studio 2008客戶端應用程序。 沒問題。 但是使用Delphi 2007是一個不同的問題。 我可以使用Delphi中的WSDL導入器從(在這種情況下) http:// bernard3:8000 / VMWareProvisioning / Service?wsdl中檢索WSDL導入單元編譯得很好。 我必須手動初始化代理,因為WSDL不包含URL(注意C#代碼中顯示的額外“/ CoreServices”):

var
  Auth: AuthenticateUser;
  AuthResponse: AuthenticateUserResponse;
  CoreI: IVMProvisionCore;
begin
  CoreI:= GetIVMProvisionCore(False, 'http://bernard3:8000/VMWareProvisioning/Service/CoreServices');
  Auth:= AuthenticateUser.Create;
  try
    Auth.username:= 'test';
    Auth.password:= 'test';
    AuthResponse:= CoreI.AuthenticateUser(Auth);
  finally
    FreeAndNIL(Auth);
  end;

上面的代碼在遇到“CoreI.AuthenticateUser(Auth);”時會產生錯誤。 錯誤是“ 無法處理消息,因為內容類型'text / xml; charset =”utf-8“不是預期類型'application / soap + xml; charset = utf-8。

我懷疑我在某處有一個愚蠢的小錯誤,可能是在導入WSDL或連接選項之類的時候。 有人可以幫忙嗎?

找到了解決方案。 它是多個部分,需要對C#端進行一些更改,對Delphi端更多。 請注意,這是使用Delphi 2007和Visual Studio 2008測試的。

C#side:使用BasicHttpBinding而不是WSHttpBinding。

修復第1步

BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.Security.Mode = BasicHttpSecurityMode.None;

此更改將解決Delphi端的application / soap + xml錯誤。

Delphi 2007方面:針對修改后的C#Web服務運行現在將生成如下錯誤:

由於EndpointDispatcher上的ContractFilter不匹配,因此無法在接收方處理帶有消息'帶有Action的消息'的異常類ERemotableException。 這可能是由於合同不匹配(發送方與接收方之間的操作不匹配)或發送方與接收方之間的綁定/安全性不匹配。 檢查發送方和接收方是否具有相同的合同和相同的綁定(包括安全要求,例如消息,傳輸,無)。

要解決此問題,請將SOAPActions添加到所有支持的接口。 這是我的代碼中的示例; 這必須在import-from-WSDL-PAS-file的初始化部分所做的所有InvRegistry更改之后完成:

修復第2步

InvRegistry.RegisterDefaultSOAPAction(TypeInfo(IVMProvisionCore), 'http://Cisco.VMProvision.Core/CoreServices/%operationName%');

類型名稱和URL應該可以從Delphi生成的WSDL導入文件和/或實際WSDL的檢查中獲得。 上面的例子是我自己的項目。 這些代碼更改后,您將出現錯誤:

帶有消息的異常類ERemotableException'格式化程序在嘗試反序列化消息時引發異常:反序列化請求消息正文以進行操作時出錯....

通過添加以下代碼解決此錯誤(信用到http://www.bobswart.nl/weblog/Blog.aspx?RootId=5:798 )。 同樣,這個新代碼必須在WSDL-to-PAS文件初始化之后的所有InvRegistry之后。

修復第3步

InvRegistry.RegisterInvokeOptions(TypeInfo(IVMProvisionCore), ioDocument);

此時,數據包將在Delphi和C#之間來回傳遞 - 但參數將無法正常工作。 C#將接收所有參數作為空值,Delphi似乎沒有正確接收響應參數。 最后的代碼步驟是使用稍微定制的THTTPRIO對象,該對象將允許文字參數。 這部分的技巧是確保在獲得接口后應用該選項; 之前這樣做是行不通的。 這是我的例子中的代碼(只是片段)。

修復第4步

var
  R: THTTPRIO;
  C: IVMProvisionCore;
begin
  R:= THTTPRIO.Create(NIL);
  C:= GetIVMProvisionCore(False, TheURL, R);
  R.Converter.Options:= R.Converter.Options + [soLiteralParams];

現在 - 我的Delphi 2007應用程序可以與C#,獨立,非IIS,WCF Web服務進行通信!

這是由SOAP版本不匹配引起的。 C#服務期待SOAP12消息並從您的Delphi應用程序接收SOAP11消息。 根據您的情況,您需要更改雙方中的任何一方。 我無法真正評論德爾福方面。 在WCF端,您可以使用默認為SOAP11的BasicHttpBinding,或者,如果需要更多控制,請使用指定SOAP11的消息類型的CustomBinding。

在delphi中使用C#Web服務時,我也遇到了同樣的問題。
Delphi 7.0 / 2005/2007不支持新的WSDL定義。
為此,您需要下載最新的WSDL Importer(WSDLImp.exe)。 它還將提供更新的delphi源代碼傳遞文件的源代碼。

謝謝 - 這幫了很多忙。 我有幾個皺紋的麻煩。 對我來說,問題#2(SOAPAction)都被搞砸了,因為OperationName不匹配。 .Net小組標准化了在SOAPAction結尾處放置“In”,但沒有標准化操作。
所以yadda.yadda.com/whatever/services/%operationName%確實需要是yadda.yadda.com/whatever/services/%operationName%In在這種特定情況下。

我花了很長時間才發現這一點,但我最終注意到與SoapUI並行測試,它與錯誤響應中返回的SOAPActions不同。 我解決了這個問題,並且有效。 但這是在經過一段時間努力試圖弄清楚DefaultSOAPAction應該是什么之后。 再次,SoapUI在這里很有幫助。
所以無論如何,如果你發現你得到這個錯誤:“由於EndpointDispatcher上的ContractFilter不匹配,無法在接收者處理動作(無論如何)......”第一步是填充DefaultSOAPAction,如果問題仍然存在,比較錯誤中報告的那個與真正應該存在的那個。
HTH,克里斯

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM