Link to home
Start Free TrialLog in
Avatar of DelphiRulez
DelphiRulez

asked on

Delphi 2010 Web service help

Delphi 2010

I am trying to creat a DB connection to a MS SQL Server 2005 DB via a web service.

I have one call

function ConnectToDB(DBAlias: String): Boolean;stdcall;


I keep getting a "Inavalid argument: VPUCDS_VPN_SE01" error


What have i done wrong in adding the function parameter "DBAlias: String" to the routine?


When I had the following code in my webservice it worked fine

function TTest.ConnectToDB: Boolean;stdcall;
var
 Conn: TSQLConnection;
begin
 Conn:= TSQLConnection.Create(nil);
 Conn.ConnectionName:= 'VPUCDS_VPN_SE01';
 Conn.LoadParamsOnConnect := True;
 Conn.LoginPrompt:=True;
 try
   Conn.Connected:= True;
   result:=  Conn.Connected;
 finally
  Conn.Free;
 end;
end;

Now that I have added the capability to pass the Alias in the call:

function ConnectToDB(DBAlias: String): Boolean;stdcall;
var
 Conn: TSQLConnection;
begin
 Conn:= TSQLConnection.Create(nil);
 Conn.ConnectionName:= DBAlias;
 Conn.LoadParamsOnConnect := True;
 Conn.LoginPrompt:=True;
 try
   Conn.Connected:= True;
   result:=  Conn.Connected;
 finally
  Conn.Free;
 end;
end;


 i get the error

"Inavalid argument: VPUCDS_VPN_SE01"

see both the web service server and web service client code here:

http://www.shaneholmes.net/tmp/demo.zip


Thanks

Shane
Avatar of systan
systan
Flag of Philippines image

If is not a dll, Try to remove < stdcall; >   In stdcall, the parameters are removed by the called function.
if it is a dll,  Try to change to < export; stdcall;  >
Avatar of DelphiRulez
DelphiRulez

ASKER

its a webservice....CGI...and i believe its required
Where did you place the .ini files? Are you sure the web service can find them? Make sure they are in the working directory, which may be different than the virtual directory where the CGI executable is deployed...

(and stdcall is required for SOAP methods, so leave that inside)
The ini files are in the folder with the executable and the DLL files.

Again, everything works great when the call is

function TTest.ConnectToDB: Boolean;stdcall;


but when i have

function ConnectToDB(DBAlias: String): Boolean;stdcall;


it fails
So

 Conn.ConnectionName:= DBAlias;

fails, but

 Conn.ConnectionName:= 'VPUCDS_VPN_SE01';

works just fine ???



Change the function ConnectToDB(DBAlias: String): String; to return the string instead of a Boolean.

Set

  Result := DBAlias

and in the client check what the string is that's returned.


Double-check to see that you are calling the right web service - the one you've deployed. And that the .ini files are in that place as well.
function ConnectToDB( Const DBAlias: String ): Boolean;stdcall;
Systan: that's already the definition of the import routine:


  ITest = interface(IInvokable)
  ['{26F3F2AB-E760-9AA7-5A90-364B402E45E9}']
    function  ConnectToDB(const DBAlias: string): Boolean; stdcall;
  end;

Open in new window

So, instead of a webservice, here is a test executable i placed in the same folder with ini files and dll files and it worked just fine

unit UntMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, SQLExpr, StdCtrls, DBXMsSQL, MidasLib;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
 Conn: TSQLConnection;
begin
 Conn:= TSQLConnection.Create(nil);
 Conn.ConnectionName:= 'VPUCDS_VPN_SE01';
 Conn.LoadParamsOnConnect := True;
 Conn.LoginPrompt:=True;
 try
   Conn.Connected:= True;
   if Conn.Connected then
   ShowMessage('Connected!')
   else
   ShowMessage('NOT Connected!')
 finally
  Conn.Free;
 end;
end;

end.



I will try you suggestions bob

//ADD const before declaring a string variable of your function parameter
function ConnectToDB( Const DBAlias: String ): Boolean;stdcall;

>Systan: that's already the definition of the import routine:
Yes, it is, but to remain it constant as it was
code from test application (WORKS!) Aopplication executable running in my web service folder just for testing purposes

procedure TForm1.Button1Click(Sender: TObject);
var
 Conn: TSQLConnection;
begin
 Conn:= TSQLConnection.Create(nil);
 Conn.ConnectionName:= 'VPUCDS_VPN_SE01';
 Conn.LoadParamsOnConnect := True;
 Conn.LoginPrompt:=True;
 try
   Conn.Connected:= True;
   if Conn.Connected then
   ShowMessage('Connected!')
   else
   ShowMessage('NOT Connected!')
 finally
  Conn.Free;
 end;
end;





code from the actual Web service test(DOES NOT WORK!)

Notice i am not even passing the parameter (DBAlias)...instead, i hard code it



function TTest.ConnectToDB: Boolean;stdcall;
var
 Conn: TSQLConnection;
begin
 Conn:= TSQLConnection.Create(nil);
 Conn.ConnectionName:= 'VPUCDS_VPN_SE01';  
 Conn.LoadParamsOnConnect := True;
 Conn.LoginPrompt:=True;
 try
   Conn.Connected:= True;
   result:=  Conn.Connected;
 finally
  Conn.Free;
 end;
end;

so, im getting ""Inavalid argument: VPUCDS_VPN_SE01"  and i not even passing a Alias,
Have you tried removing the stdcall ?

Stdcall is recommended, but its not required always.
yes, i tried
Ok, Thanks, Listening only...
So basically, you cannot connect as a Web Service,, even if the alias is hardcoded.

So the problem is not passing the Alias, the problem is assigning the Alias to the ConnectionName.

Most likely, the web service executable (CGI) is unable to find or read the .ini files. The working directory of the CGI executables could be different.

Check your IIS settings, and verify what the working directory of your virtual directory is (see the application  settings).
Talking..
Ok check your TSQLConnection object properties, maybe VPUCDS_VPN_SE01 location is NOT pointed for web or in different location,  thats why its only working on standalone application
One more check: if you use MS SQL, then often the default internet user cannot access the database using OSAuthentication. Make sure OSAuthentication is off.
checking that stuff now
ok, for authentication, i have:

Anonymous : Enabled
Basic : Disabled
Windows: Disabled


Under basic Settings for Virtual Directory,  I have

C:\inetpub\wwwroot\shanedev\

which is the folder i have the DLLs and INi Files in and where the test app worked fine, but the web service one did not
How do I tell TSqlConnection where the ini files are?
The location of the .ini files is not the problem if the hardcoded alias also doesn't work... I have the feeling you are not allowed to connect to the database...
but i can with a non web service exe from that same path
Yes, but a non-web service runs "as you" (a user, logged on into windows), and not as "default internet user" (which is the user that your CGI executable executes as), who has very little permissions on your machine and usually cannot connect to SQL Server databases for example.
sorry, i don't understand. Can you tell me how to change the permissions on IIS7?   I litterally have no experience with IIS7. I configured it using your e-book and marco cantus's info. Again, I can make a Web service run, I have created many demos (non database ones)....so I guess what i need is permissions to the DB from the web services folder (wwwroot\shanedev\) ??????

Im totally lost and very frustrated, Ive spent way too many hours i trying to do something that in the beginning i thought would be simple.
ASKER CERTIFIED SOLUTION
Avatar of ebob42
ebob42
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Im using SQL Server 2005 on a MS Server 2008 machine

I have access via a VPN, since its my company's machine located in Seattle. Im in NY

Thanks for your help anyways

shane
I have also gave the following a try:

SERVER CODE:

function TTest.ConnectToDB: Boolean;stdcall;
var
 Conn: TSQLConnection;
 Ex: ConnectionException;
begin
 Conn:= TSQLConnection.Create(nil);
 Conn.ConnectionName:= 'VPUCDS_VPN_SE01';
 Conn.LoadParamsOnConnect := True;
 Conn.LoginPrompt:=False;
 try
   Conn.Connected:= True;
   result:=  Conn.Connected;
   Conn.Free;
 except
 begin
  Ex:= ConnectionException.Create('Connection Failed!');
  raise Ex;
 end;
 end;
end;

CLIENT CODE:

procedure TForm1.Button1Click(Sender: TObject);
begin
  try
  GetITest.ConnectToDB;
  except on E: ConnectionException do
   ShowMessage(E.ClassName + ': ' + E.Message + #10#13 +
               'FaultActor: ' + E.FaultActor + #10#13 +
               'FaultCode: ' + E.FaultCode + #10#13 +
               'FaultDetail: ' + E.FaultDetail + #10#13 +
               'FaultReason: ' + E.FaultReason + #10#13 +
               'FaultReasonLang: ' + E.FaultReasonLang + #10#13 +
               'FaultNode: ' + E.FaultNode +#10#13 +
               'FaultRole: ' + E.FaultRole);
  end;
end;
end.


I didn't learn anything from the response

see screenshot here: http://www.shaneholmes.net/tmp/screenshot.jpg

again, I can run a standard delphi app executable from the same folder (wwwroot) and conenct to the database, i just can't do it with a web service executable. However, I can create demo web services that work as long as they are not DB related.