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

+3


source to share


1 answer


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

.

+1


source







All Articles