Si hallas algún fallo con tu código o trabajo, recuerda probar siempre en un ambiente de testing antes subir el código al proyecto final.
Solución:
En un momento hubo una discusión sobre el error en una conversación ahora borrada hace mucho tiempo de los foros de Embarcadero, por Bruneau Babet, un miembro del personal de Embarcadero.
Bruno dijo:
Hola,
He publicado una versión parcheada de SOAPHTTPTrans.pas que contiene una solución para este problema aquí:
[forum link redacted, it didn’t work anymore anyways, the post is gone]
Aún puede anular el evento como se describe en la sección C ++ Builder referida; o, mucho más simple, al menos para los usuarios de Delphi, simplemente agregue el SOAPHTTPTrans.pas actualizado al proyecto de su aplicación. Háganos saber si eso no funciona para usted.
Salud,
Bruneau
Puede obtener la reparación y las notas al respecto en su formato de foro original desde el siguiente enlace de pastebin y en bitbucket para que no tenga que extraer el archivo del texto circundante.
Actualización de Warren 2016: Alguien que intentó usar la solución en Delphi XE me informó que esta solución NO funciona para ellos en Delphi XE. Se agradecería cualquier actualización adicional del código en bitbucket que resuelva los errores restantes.
Me encontré con el El identificador está en un estado incorrecto para la operación solicitada en noviembre de 2018 usando Delphi Tokyo 10.2.3, luego miró el parche de código en el enlace de pastebin debajo de la respuesta de Arjen.
Ese código es muy antiguo y el código de prueba ya no funciona (el servicio SOAP no está disponible). Además, no está claro en el código de Bruneau. qué parcheó exactamente.
Comparando esa fuente y la de mi versión de Delphi, parece que estas son las (dos) modificaciones requeridas en el HandleWinInetError
procedimiento (‘PARCHE AQUÍ’):
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;
Tenga en cuenta que el RaiseError El parámetro de procedimiento ni siquiera se usó antes de este parche 😉
Aquí hay un código de prueba que utiliza el servicio SOAP del servicio web SOAP de la base de datos nacional de pronóstico digital (NDFD) de la NOAA:
Uses SOAP.SOAPHTTPTrans;
const Request2 =
'' +
' ' +
' ' +
' ' +
' 38.9936 ' +
' -77.0224 ' +
' %tomorrow% ' +
' 5 ' +
' e ' +
' 12 hourly ' +
' ' +
' ' +
' ';
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;
Sin se detectan los errores de parche en el extremo final de la URL, pero los errores en el nombre de dominio solo desencadenan un mensaje de error vacío.
Con el parche esos también están atrapados.
He informado del problema en RAD Studio Quality Portal con el número RSP-21862
Úselo bajo su propio riesgo e informe cualquier hallazgo adicional.
Adición: El problema se solucionó en diciembre de 2018 en Delphi 10.3 Rio y el problema del Portal de calidad se cerró con la siguiente observación:
En RAD Studio 10.3, la implementación de THTTPReqResp se cambió y se reemplazó por THTTPClient. Entonces, este problema ya no se aplica.
No he verificado esto.
Sección de Reseñas y Valoraciones
Eres capaz de ayudar nuestra ocupación poniendo un comentario y valorándolo te damos la bienvenida.