I'm having a VERY strange behavior with MSXML2.ServerXMLHTTP
/MSXML2.XMLHTTP.3.0
.
The problem is with the send
method. which can accept BSTR
/SAFEARRAY
/XMLDOC
object/IStream
This code works fine and worked for years (the usage of FServiceUrl, FReqXML
naming is 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 into 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;
Strangely, the above line xmlHttp.send(FReqXML);
is raising an exception:
EOleException: "the parameter is incorrect"
Notice that FReqXML
types are identical in both cases (WideString/BSTR
)
A 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 simply cannot understand why this exception occurs!
If I explicitly "convert" FReqXML
to WideString
with VarToWideStr
in TXMLHttpNet.PostRequest
it works ok:
xmlHttp.send(VarToWideStr(FReqXML));
Or even strangely like this (!):
xmlHttp.send((FReqXML)); // note the double Brackets
Question: What is going on here?
From what I can tell FReqXML
is a WideString/BSTR
in both cases.
Why is FReqXML
parameter behaves differently in the two situations?
You're right that FReqXML
is of the same type in both cases, but in the latter case, its memory is allocated in relation to the object's memory (heap). Depending on the Delphi version and the compiler settings, this may cause different behaviour of the memory used for the string than for local use only (stack). Which is why VarToWideStr
does work (and oddly enough extra parentheses also apparently).
Apart from that, I would very strongly recommend importing the MSXML2 type library and using that. It uses early binding, and that not only improves performance, it enabled code-completion in the code editor.
You could use the Type Library importer to generate it, or use a copy I have here.
Then, don't use OleVariant
and CreateOleObject
(which causes late binding), but use CoServerXMLHTTP.Create
and the XMLHTTP
interface type.