Delphian
asked on
How I can use a TClientDataset (of VCL.NET) in a ASP.NET WebService.
Hi Experts,
After days examining different ways to consume a ADO.NET dataset sent
by a webservice method, I found that article of DrBob (http://www.drbob42.com/examines/examin62.htm)
which gave the idea to use the ADONETConnector to take the data to ClientDataset and save it to a
XML string.
The code for the function is below:
function ObterXMLDataPacket(
pADONET_Dataset: DataSet; pNumero_DataTable: Integer): String;
var Conector:TADONETConnector;
Cds:TclientDataset;
DSP:TDatasetProvider;
St: TStringStream;
begin
If pADONET_Dataset.Tables.Cou nt = 0 then Exit;
(*Cria os componentes necessários*)
Cds := TClientDataSet.Create(nil) ;
DSP := TDataSetProvider.Create(ni l);
St := TStringStream.Create;
Conector := TADONETConnector.Create(ni l);
(*Conecta os componentes*)
DSP.Dataset := Conector;
Cds.SetProvider(DSP);
Conector.DataTable := pADONET_Dataset.Tables[pNu mero_DataT able];
(*Obtém os dados*)
Conector.Open;
CDS.Open; // Here the method throws the exception
(*Transforma os dados em XML Datapacket*)
Cds.SaveToStream(St,dfXML) ;
Result := ST.DataString;
(*Limpa o ambientes*)
St.Free;
Cds.Free;
Conector.Free;
DSP.Free;
end;
The function is used in a WebMethod which opens a BDPDataAdapter and calls the function with the Dataset
populated by the Adapter.
Here is the code:
function TCC_DataLayer.RetornaDatas etXMLDPack et: String;
begin
BdpDataAdapter1.Active := True;
Result := ObterXMLDataPacket(ds1,0);
end;
With the needed units (ADONetDb, System.Data, etc among a few other ones) - the WebService build without problems. But when the method is called, the execution is aborted with a exception (on the Win32 client, on the browser gave only a internal server error).
Here is the message of the Exception: "Servidor não pôde processar a solicitação. --> Invalid threading model (STAThreadAttribute is required)"
The first part is in Brazilian Portuguese and means: "Server could not process the request"
Here is the code where the WebMethod is called:
procedure TForm2.Button2Click(Sender : TObject);
var Comm:THTTPRIO;
begin
Comm := THTTPRIO.Create(nil);
WServico := GetTCC_DataLayerSoap(False ,'http://localhost/CredCob_DataLayer/uCC_DataLayer.asmx',Comm);
try
ClientDataSet1.XMLData := WServico.RetornaDatasetXML DPacket;
ClientDataSet1.Open;
except
on E: Exception do
begin
With TStringList.Create do
begin
Add(E.Message);
SaveToFile('c:\mensagemerr o.txt');
Free;
end;
end;
end;
end;
Environment: Delphi 2006 Architect (Borland® Developer Studio for Microsoft® Windows™ Version 10.0.2288.42451 Update 2), IIS + ASP.NET 1.1.4322...
DataBase: MSSQL 2005 (just for the sake of completeness).
Best Regards and thank you very much for the attention,
Fabricio (Delphian)
After days examining different ways to consume a ADO.NET dataset sent
by a webservice method, I found that article of DrBob (http://www.drbob42.com/examines/examin62.htm)
which gave the idea to use the ADONETConnector to take the data to ClientDataset and save it to a
XML string.
The code for the function is below:
function ObterXMLDataPacket(
pADONET_Dataset: DataSet; pNumero_DataTable: Integer): String;
var Conector:TADONETConnector;
Cds:TclientDataset;
DSP:TDatasetProvider;
St: TStringStream;
begin
If pADONET_Dataset.Tables.Cou
(*Cria os componentes necessários*)
Cds := TClientDataSet.Create(nil)
DSP := TDataSetProvider.Create(ni
St := TStringStream.Create;
Conector := TADONETConnector.Create(ni
(*Conecta os componentes*)
DSP.Dataset := Conector;
Cds.SetProvider(DSP);
Conector.DataTable := pADONET_Dataset.Tables[pNu
(*Obtém os dados*)
Conector.Open;
CDS.Open; // Here the method throws the exception
(*Transforma os dados em XML Datapacket*)
Cds.SaveToStream(St,dfXML)
Result := ST.DataString;
(*Limpa o ambientes*)
St.Free;
Cds.Free;
Conector.Free;
DSP.Free;
end;
The function is used in a WebMethod which opens a BDPDataAdapter and calls the function with the Dataset
populated by the Adapter.
Here is the code:
function TCC_DataLayer.RetornaDatas
begin
BdpDataAdapter1.Active := True;
Result := ObterXMLDataPacket(ds1,0);
end;
With the needed units (ADONetDb, System.Data, etc among a few other ones) - the WebService build without problems. But when the method is called, the execution is aborted with a exception (on the Win32 client, on the browser gave only a internal server error).
Here is the message of the Exception: "Servidor não pôde processar a solicitação. --> Invalid threading model (STAThreadAttribute is required)"
The first part is in Brazilian Portuguese and means: "Server could not process the request"
Here is the code where the WebMethod is called:
procedure TForm2.Button2Click(Sender
var Comm:THTTPRIO;
begin
Comm := THTTPRIO.Create(nil);
WServico := GetTCC_DataLayerSoap(False
try
ClientDataSet1.XMLData := WServico.RetornaDatasetXML
ClientDataSet1.Open;
except
on E: Exception do
begin
With TStringList.Create do
begin
Add(E.Message);
SaveToFile('c:\mensagemerr
Free;
end;
end;
end;
end;
Environment: Delphi 2006 Architect (Borland® Developer Studio for Microsoft® Windows™ Version 10.0.2288.42451 Update 2), IIS + ASP.NET 1.1.4322...
DataBase: MSSQL 2005 (just for the sake of completeness).
Best Regards and thank you very much for the attention,
Fabricio (Delphian)
ASKER
You mean apply the attibute to the WebMethod? Does not work.
And even putting in both (internal function and WebMethod), or
in one of them - does not work, the exception is thrown wherever
the attribute is located...
Any ideas?
And even putting in both (internal function and WebMethod), or
in one of them - does not work, the exception is thrown wherever
the attribute is located...
Any ideas?
[STAThread]
static void Main()
{
}
This way you change the Threading Model to Single Threaded.
static void Main()
{
}
This way you change the Threading Model to Single Threaded.
ASKER
No luck on this also...
No more ideas on my side... Sorry.
ASKER
I did some additional testing, the results are:
-> In a desktop Windows Forms: OK (no changes, no additional attributes needed)
-> In a desktop VCL.NET: OK (ditto above)
The great trouble is when ASP.NET Web Services come in scene. Seems a agreement
that someone needs to get a STAThread attrib... But is not the likely ones.
So, the 500 points question: WHERE I put the this 'lovely' attribute? Or is not an attribute
question?
Any comments?
(BTW: Thank you for the good will, Ivanov)
-> In a desktop Windows Forms: OK (no changes, no additional attributes needed)
-> In a desktop VCL.NET: OK (ditto above)
The great trouble is when ASP.NET Web Services come in scene. Seems a agreement
that someone needs to get a STAThread attrib... But is not the likely ones.
So, the 500 points question: WHERE I put the this 'lovely' attribute? Or is not an attribute
question?
Any comments?
(BTW: Thank you for the good will, Ivanov)
ASKER
I discovered later that it's reported on Borland Quality Central at
http://qc.borland.com/wc/qcmain.aspx?d=33679
And after that I forgot the question. It's a real shame.
Since I changed the implementation, there's no use for me the
workaround on the link, but I ask you just to mantain the question
on the DB - it can help others.
But I would like the refund.
http://qc.borland.com/wc/qcmain.aspx?d=33679
And after that I forgot the question. It's a real shame.
Since I changed the implementation, there's no use for me the
workaround on the link, but I ask you just to mantain the question
on the DB - it can help others.
But I would like the refund.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
[STAThreadAttribute]
function TCC_DataLayer.RetornaDatas
....