MSXML2.ServerXMLHTTP late link "submit" method with BSTR fails with "parameter is invalid"
I have VERY strange behavior with MSXML2.ServerXMLHTTP
/ MSXML2.XMLHTTP.3.0
.
The problem lies in the method send
. which can take an object BSTR
/ SAFEARRAY
/ XMLDOC
object /IStream
This code works fine and has worked for many years (the use of names is FServiceUrl, FReqXML
intentional):
procedure PostRequest(const FServiceUrl, FReqXML: WideString);
var
xmlHttp: OleVariant;
begin
xmlHttp := CreateOleObject('MSXML2.ServerXMLHTTP.6.0');
xmlHttp.Open('POST', FServiceUrl, False);
// VarType(FReqXML) -> BSTR
xmlHttp.send(FReqXML);
end;
Now I needed to wrap this procedure in a simple class:
type
TXMLHttpNet = class
private
FServiceUrl: WideString;
FReqXML: WideString;
public
constructor Create(const AServiceUrl, AReqXML: WideString);
procedure PostRequest;
end;
constructor TXMLHttpNet.Create(const AServiceUrl, AReqXML: WideString);
begin
FServiceUrl := AServiceUrl;
FReqXML := AReqXML;
end;
procedure TXMLHttpNet.PostRequest; // Problem is in this call
var
xmlHttp: OleVariant;
begin
xmlHttp := CreateOleObject('MSXML2.ServerXMLHTTP.6.0');
xmlHttp.Open('POST', FServiceUrl, False);
// VarType(FReqXML) -> BSTR
xmlHttp.send(FReqXML); // EOleException: "the parameter is incorrect"
end;
Oddly enough, the above line xmlHttp.send(FReqXML);
throws an exception:
EOleException: "parameter is invalid"
Note that the types are FReqXML
identical in both cases ( WideString/BSTR
)
Simple test:
uses ComObj;
procedure TForm1.Button1Click(Sender: TObject);
var
Request: TXMLHttpNet;
begin
// simple procedure
PostRequest('http://www.gmail.com', 'foo'); // OK!
// via object method
Request := TXMLHttpNet.Create('http://www.gmail.com', 'foo');
Request.PostRequest; // EOleException: "the parameter is incorrect"
Request.Free;
end;
I just don't understand why this exception is happening!
If I explicitly "convert" FReqXML
to WideString
from VarToWideStr
to TXMLHttpNet.PostRequest
, it works fine:
xmlHttp.send(VarToWideStr(FReqXML));
Or even strange how it is (!):
xmlHttp.send((FReqXML)); // note the double Brackets
Question: What's going on here?
From what I can tell, it FReqXML
is in both cases.
Why does the parameter behave differently in two situations? WideString/BSTR
FReqXML
source to share
You are correct that it FReqXML
has the same type in both cases, but in the latter case its memory is allocated relative to the memory of the object (heap). Depending on the Delphi version and compiler options, this may cause the memory used for string behavior rather than for local use (stack). This is why it VarToWideStr
really works (and oddly enough, the extra parentheses).
Also, I highly recommend importing the MSXML2 type library and using it. It uses early binding and not only improves performance, but also allows you to complete code execution in the code editor.
You can use the type library importer to create it, or you can use the copy I'm here .
Then don't use OleVariant
and CreateOleObject
(which causes late binding), but use the CoServerXMLHTTP.Create
interface type as well XMLHTTP
.
source to share