English 中文(简体)
缩略语 “所要求操作的操作在错误状态中”
原标题:SOAP client in Delphi "The handle is in the wrong state for the requested operation"

我已在视力演播室建造了最简便和最简单的SOAP服务器,在大约3个点点。 视力室2010年的确切步骤: 首先创立了一个新项目,作为网络应用,然后添加一个新的类型网络服务项目。 (见https://stackoverflow.com/questions/8188997/how-do-i-create-a-simple-soap-server-using-c-sharp-in-音像-studio-2010/8189138#8189138) 页: 1 该台式服务器服务1 采用一种简单的方法:

利用WSDL进口商创建的客户服务1.pas的一台刀。

  IService1 = interface(IInvokable)
  [ {967498E8-4F67-AAA5-A38F-F74D8C7E346A} ]
    function  GetData(const value: Integer): string; stdcall;
    function  GetDataUsingDataContract(const composite: CompositeType2): CompositeType2; stdcall;
  end;

当我尝试采用这种方法时,就如:

procedure TForm3.Button1Click(Sender: TObject);
var
 rio : THTTPRIO;
 sv:IService1;
 addr : string;
 data : string;
begin
    //addr :=  .... ; // url from visual studio 2010 live debug instance.
    rio := THTTPRIO.Create(nil);
    sv := GetIService1( true, addr, rio );
    try
        data := sv.GetData(  0);

        Button1.Caption := data;

    finally
        sv := nil;

        rio.Free;
    end;
 end;

The error I get is this:

ESOAPHTTPException: 
 The handle is in the wrong state for the requested operation -    
 URL:http://localhost:8732/Design_Time_Addresses/WcfServiceLibrary1/Service1/ -      
 SOAPAction:http://tempuri.org/IService1/GetData .

当我把上述卢尔带上网络浏览器时,URL会进行罚款,因此,关于德尔菲的《SOAP法》倾向于不注意到吉卜赛人协会的失败的通常答案似乎是不可能的。 相反,我似乎要么(a) 在WinInet(一些窗口的出现)经历断裂,要么(b) 做错?

在我看来,任何安装了视觉演播室和德尔菲的人都应能够尝试在视力演播室与德尔菲的肥皂客户交谈时,让德米开端的Sap服务器上台,而没有任何努力。 但我不能说出最简单的事情。

最佳回答

曾经有过一次讨论,讨论过从禁运论坛删除以来很久的谈话中的错误。

布鲁诺说:

Hello,

I ve posted a patched version of SOAPHTTPTrans.pas that contains a fix for this issue here:

[经重新调整后,该员额不再工作,]

You may still override the event as described in the C++Builder section referred; or, much simpler, at least for Delphi users, simply add the updated SOAPHTTPTrans.pas to your app s project. Let us know if that does not work for you.

Cheers,

Bruneau

您可在原论坛格式中从以下网站获得修理和说明:pastebin链接,和bitbucket 。 因此,你不必从周围案文中提取文件。

<Warren Update2016: 一些人试图利用Delphi XE的固定点告诉我,这一固定点在Delphi XE为他们工作。 如能进一步修订《守则》,解决剩余的难题,将不胜感激。

问题回答

I ran into the The handle is in the wrong state for the requested operation issue in November 2018 using Delphi Tokyo 10.2.3, then looked at the code patch in the pastebin link under Arjen s answer.

That code is very old and the test code no longer works (SOAP service unavailable). Also, it is unclear from Bruneau s code what he patched exactly.

与这一来源和我的Delphi版本相比,这些来源似乎需要修改<代码>。 HandleWinInetError procedure (PATCH HERE ):

function THTTPReqResp.HandleWinInetError(LastError: DWord; 
                                         Request: HINTERNET;
                                         RaiseError: Boolean): DWord;

  function CallInternetErrorDlg: DWord;
  var
    P: Pointer;
  begin
    Result := InternetErrorDlg(GetDesktopWindow(), Request, LastError,
                               FLAGS_ERROR_UI_FILTER_FOR_ERRORS or
                               FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS or
                               FLAGS_ERROR_UI_FLAGS_GENERATE_DATA, P);

    { After selecting client certificate send request again,
      Note: InternetErrorDlg always returns ERROR_SUCCESS when called with
            ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED }
    if LastError = ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED then
      Result := ERROR_INTERNET_FORCE_RETRY;
  end;

const
  { Missing from our WinInet currently }
  INTERNET_OPTION_CLIENT_CERT_CONTEXT = 84;

var
  Flags, FlagsLen, DWCert, DWCertLen: DWord;
  ClientCertInfo: IClientCertInfo;
  CertSerialNum: string;
{$IFDEF CLIENT_CERTIFICATE_SUPPORT}
  hStore: HCERTSTORE;
  CertContext: PCERT_CONTEXT;
{$ENDIF}
begin
  { Dispatch to custom handler, if there s one }
  if Assigned(FOnWinInetError) then
    Result := FOnWinInetError(LastError, Request)
  else
  begin
    Result := ERROR_INTERNET_FORCE_RETRY;
    { Handle INVALID_CA discreetly }
    if (LastError = ERROR_INTERNET_INVALID_CA) and (soIgnoreInvalidCerts in InvokeOptions) then
    begin
      FlagsLen := SizeOf(Flags);
      InternetQueryOption(Request, INTERNET_OPTION_SECURITY_FLAGS, Pointer(@Flags), FlagsLen);
      Flags := Flags or SECURITY_FLAG_IGNORE_UNKNOWN_CA;
      InternetSetOption(Request, INTERNET_OPTION_SECURITY_FLAGS, Pointer(@Flags), FlagsLen);
    end
    else if (LastError = ERROR_INTERNET_SEC_CERT_REV_FAILED) and (soIgnoreInvalidCerts in InvokeOptions) then
    begin
      FlagsLen := SizeOf(Flags);
      InternetQueryOption(Request, INTERNET_OPTION_SECURITY_FLAGS, Pointer(@Flags), FlagsLen);
      Flags := Flags or SECURITY_FLAG_IGNORE_REVOCATION;
      InternetSetOption(Request, INTERNET_OPTION_SECURITY_FLAGS, Pointer(@Flags), FlagsLen);
    end
{$IFDEF CLIENT_CERTIFICATE_SUPPORT}
    else if (LastError = ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED) and
             Supports(Self, IClientCertInfo, ClientCertInfo) and
             (ClientCertInfo.GetCertSerialNumber <>   ) then
    begin
      CertSerialNum := ClientCertInfo.GetCertSerialNumber();
      hStore := ClientCertInfo.GetCertStore();
      if hStore = nil then
      begin
        hStore := CertOpenSystemStore(0, PChar( MY ));
        ClientCertInfo.SetCertStore(hStore);
      end;
      CertContext := FindCertWithSerialNumber(hStore, CertSerialNum);
      if CertContext <> nil then
      begin
        ClientCertInfo.SetCertContext(CertContext);
        InternetSetOption(Request, INTERNET_OPTION_CLIENT_CERT_CONTEXT,
                          CertContext, SizeOf(CERT_CONTEXT));
      end
      else
      begin
        if RaiseError then RaiseCheck(LastError);  // PATCH HERE
        Result := CallInternetErrorDlg;
      end;
    end
{$ENDIF}
    else if (LastError = ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED) and (soPickFirstClientCertificate in InvokeOptions) then
    begin
      { This instructs WinInet to pick the first (a random?) client cerficate }
      DWCertLen := SizeOf(DWCert);
      DWCert := 0;
      InternetSetOption(Request, INTERNET_OPTION_SECURITY_SELECT_CLIENT_CERT,
                        Pointer(@DWCert), DWCertLen);
    end
    else
    begin
      if RaiseError then RaiseCheck(LastError);  // PATCH HERE
      Result := CallInternetErrorDlg;
    end;
  end;
end;

注:RaiseError 程序参数在发送之前甚至没有使用;-

此处使用国家数字预报数据库(NDFD)SOAP网络服务https://graphical.weather.gov/xml/“rel=“nofollow noreferer”)。

Uses SOAP.SOAPHTTPTrans;

const Request2 =
 <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ndf="http://graphical.weather.gov/xml/DWMLgen/wsdl/ndfdXML.wsdl">  +
    <soapenv:Header/>  +
    <soapenv:Body>  +
       <ndf:NDFDgenByDay soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">  +
          <latitude xsi:type="xsd:decimal">38.9936</latitude>  +
          <longitude xsi:type="xsd:decimal">-77.0224</longitude>  +
          <startDate xsi:type="xsd:date">%tomorrow%</startDate>  +
          <numDays xsi:type="xsd:integer">5</numDays>  +
          <Unit xsi:type="dwml:unitType" xmlns:dwml="http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd">e</Unit>  +
          <format xsi:type="dwml:formatType" xmlns:dwml="http://graphical.weather.gov/xml/DWMLgen/schema/DWML.xsd">12 hourly</format>  +
       </ndf:NDFDgenByDay>  +
    </soapenv:Body>  +
 </soapenv:Envelope> ;

const URL2=  https://graphical.weather.gov:443/xml/SOAP_server/ndfdXMLserver.php ;

procedure TFrmHandleWinINetError.Button1Click(Sender: TObject);
var
  RR: THTTPReqResp;
  Response: TMemoryStream;
  U8: UTF8String;
begin
  RR := THTTPReqResp.Create(nil);
  try
    try
      RR.URL := URL2;
      RR.UseUTF8InHeader := True;
      RR.SoapAction :=  NDFDgenByDay ;
      Response := TMemoryStream.Create;
      RR.Execute(Request2, Response);
      SetLength(U8, Response.Size);
      Response.Position := 0;
      Response.Read(U8[1], Length(U8));
      ShowMessage(String(U8));
      except
        on E:Exception do ShowMessage( ERROR CAUGHT:   + e.message);
      end;
    finally
      Response.Free;
      RR.Free;
    end;
  end;
end;  

Without the patch errors in the tail end of the URL are caught, but errors in the domain name just trigger an empty error message.
With the patch those are also caught.

我在以下网址上报告了这一问题:RSP-21862

您本人有风险使用,请报告任何其他调查结果。


。 这一问题于2018年12月在Delphi 10.3 里约确定,质量门户问题以以下表述结束:

在RADroom 10.3中,实施了THTTPReqResp,改为THTTPClient。 因此,这一问题不再适用。

我没有核实这一点。





相关问题
determining the character set to use

my delphi 2009 app has a basic translation system that uses GNUGetText. i had used some win API calls to prepare the fonts. i thought it was working correctly until recently when someone from Malta ...

Help with strange Delphi 5 IDE problems

Ok, I m going nuts here. For the last (almost) four years, I ve been putting up with some extremely bad behavior from my Delphi 5 IDE. Problems include: Seemingly random errors in coride50.bpl ...

How to write a Remote DataModule to run on a linux server?

i would like to know if there are any solution to do this. Does anyone? The big picture: I want to access data over the web, using my delphi thin clients. But i´would like to keep my server/service ...

How convert string to integer in Oxygene

In Delphi, there is a function StrToInt() that converts a string to an integer value; there is also IntToStr(), which does the reverse. These functions doesn t appear to be part of Oxygene, and I can ...

Quick padding of a string in Delphi

I was trying to speed up a certain routine in an application, and my profiler, AQTime, identified one method in particular as a bottleneck. The method has been with us for years, and is part of a "...

热门标签