delphi的webservice开发。
一、在已有的项目中,调用外部的webservice
1、根据向导建webservice,在项目中引入“WSDL Importer"。假设引入后生成的类的名字为”service"
2、对生成的service类做相应的修改。
2.1、如果webservice方法里的某些参数即是接收传入参数又是接收返回参数,在delphi里要对参数名字重新命名
如在用c#写的webservice的服务端方法是sr.Get_Delivery_Data_Over(sn, sjlx, ref err); //默认生成的代码为 procedure Get_Delivery_Data(const err: WideString; const data_str: TByteDynArray; const sn: Integer; const sjlx: WideString; out Get_Delivery_DataResult: Boolean; out err: WideString; out data_str: TByteDynArray; out sn: Integer); stdcall; ///要改成如下: procedure Get_Delivery_Data(const err1: WideString; const data_str1: TByteDynArray; const sn1: Integer; const sjlx: WideString; out Get_Delivery_DataResult: Boolean; out err: WideString; out data_str: TByteDynArray; out sn: Integer); stdcall;
2.2、 如果delphi调用c#写的webservice时,服务器端方法接收到delphi传过来的参数总是为空时,在delphi的service类的initialization下面加这名话
InvRegistry.RegisterInvokeOptions(TypeInfo(ServiceSoap),ioDocument); ///必需要加,不然传到c#写的webservice里的方法的参数值是空的
如下是service类的源代码
// ************************************************************************ // // The types declared in this file were generated from data read from the // WSDL File described below: // WSDL : http://fti.yndzyf.com/Service.asmx?wsdl // Encoding : utf-8 // Version : 1.0 // (2014-05-21 16:32:33 - 1.33.2.5) // ************************************************************************ // unit Service; interface uses InvokeRegistry, SOAPHTTPClient, Types, XSBuiltIns; type // ************************************************************************ // // The following types, referred to in the WSDL document are not being represented // in this file. They are either aliases[@] of other types represented or were referred // to but never[!] declared in the document. The types from the latter category // typically map to predefined/known XML or Borland types; however, they could also // indicate incorrect WSDL documents that failed to declare or import a schema type. // ************************************************************************ // // !:string - "http://www.w3.org/2001/XMLSchema" // !:base64Binary - "http://www.w3.org/2001/XMLSchema" // !:int - "http://www.w3.org/2001/XMLSchema" // !:boolean - "http://www.w3.org/2001/XMLSchema" Websoap = class; { "http://aitf.yndzyf.com/"[H] } // ************************************************************************ // // Namespace : http://aitf.yndzyf.com/ // ************************************************************************ // Websoap = class(TSOAPHeader) private FUserName: WideString; FPassWord: WideString; published property UserName: WideString read FUserName write FUserName; property PassWord: WideString read FPassWord write FPassWord; end; // ************************************************************************ // // Namespace : http://aitf.yndzyf.com/ // soapAction: http://aitf.yndzyf.com/%operationName% // transport : http://schemas.xmlsoap.org/soap/http // binding : ServiceSoap // service : Service // port : ServiceSoap // URL : http://fti.yndzyf.com/Service.asmx // ************************************************************************ // ServiceSoap = interface(IInvokable) ['{E00EB65B-7136-E473-42EF-D3135F25019F}'] procedure Get_Delivery_Data(const err1: WideString; const data_str1: TByteDynArray; const sn1: Integer; const sjlx: WideString; out Get_Delivery_DataResult: Boolean; out err: WideString; out data_str: TByteDynArray; out sn: Integer); stdcall; procedure Get_Delivery_Data_Over(const sn: Integer; const sjlx: WideString; const err1: WideString; out Get_Delivery_Data_OverResult: Boolean; out err: WideString); stdcall; procedure Receive_data(const error1: WideString; const str: TByteDynArray; const sn: Integer; const sjlx: WideString; out Receive_dataResult: Boolean; out error: WideString); stdcall; end; function GetServiceSoap(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil;user:string='';password:string=''): ServiceSoap; implementation function GetServiceSoap(UseWSDL: Boolean; Addr: string; HTTPRIO: THTTPRIO;user:string;password:string): ServiceSoap; const defWSDL = 'http://fti.yndzyf.com/Service.asmx?wsdl'; defURL = 'http://fti.yndzyf.com/Service.asmx'; defSvc = 'Service'; defPrt = 'ServiceSoap'; var RIO: THTTPRIO; begin Result := nil; if (Addr = '') then begin if UseWSDL then Addr := defWSDL else Addr := defURL; end; if HTTPRIO = nil then RIO := THTTPRIO.Create(nil) else RIO := HTTPRIO; try Result := (RIO as ServiceSoap); if UseWSDL then begin RIO.WSDLLocation := Addr; RIO.Service := defSvc; RIO.Port := defPrt; end else RIO.URL := Addr; finally if (Result = nil) and (HTTPRIO = nil) then RIO.Free; end; end; initialization InvRegistry.RegisterInterface(TypeInfo(ServiceSoap), 'http://aitf.yndzyf.com/', 'utf-8'); InvRegistry.RegisterDefaultSOAPAction(TypeInfo(ServiceSoap), 'http://aitf.yndzyf.com/%operationName%'); InvRegistry.RegisterHeaderClass(TypeInfo(ServiceSoap), Websoap, 'Websoap', ''); RemClassRegistry.RegisterXSClass(Websoap, 'http://aitf.yndzyf.com/', 'Websoap'); InvRegistry.RegisterInvokeOptions(TypeInfo(ServiceSoap),ioDocument); ///必要要加,不然传到c#写的webservice里的值是空的 end.
3、调用
procedure Tform_smrk.bgetydClick(Sender: TObject); var sql:string; var err_fp,err1_fp,err_yjm,err1_yjm:Widestring; data_fp,data_fp1,data_yjm,data_yjm1:TByteDynArray; sn_fp,sn_fp1,sn_yjm,sn_yjm1:Integer; flag_fp,flag_fp1,flag_yjm,flag_yjm1:boolean; ws:webSoap; svc:serviceSoap; begin svc := HTTPRIO1 as ServiceSoap; ws:=websoap.Create; ws.UserName:=serviceName;///webservice的用户名和密码 ws.PassWord:=servicePassword; (svc as ISOAPHeaders).Send(ws); svc.Get_Delivery_Data('',data_fp1,0,'运单',flag_fp,err_fp,data_fp,sn_fp); (svc as ISOAPHeaders).Send(ws);///每次调用时都要重新设置用户和密码 svc.Get_Delivery_Data('',data_yjm1,0,'电子监管',flag_yjm,err_yjm,data_yjm,sn_yjm); if length(data_fp)>0 then///如果有运单 begin ADOStoredProc1.ProcedureName:= 'p_insert_data'; ADOStoredProc1.Parameters.Clear; ADOStoredProc1.Parameters.Refresh; ADOStoredProc1.Parameters.ParamByName('@data_str').Value:=data_fp; if length(data_yjm)>0 then ADOStoredProc1.Parameters.ParamByName('@data_str_yjm').Value:=data_yjm; ADOStoredProc1.Prepared; ADOStoredProc1.ExecProc; end
要注意的是:1、每次调用webservice时要重新写一次(svc as ISOAPHeaders).Send(ws);,将webSoap和serviceSoap关联
2、上面的代码是从webservice取xml的二进制文件,然后将取出的二进制数据传入到存储过程p_insert_data里。用ADOStoreProc可以对存储过程传参数
时可以不考虑参数的类型,直接用ADOStoredProc1.Parameters.ParamByName('@data_str').Value:=data_fp赋值,在赋值前要ADOStoredProc1.Parameters.Refresh;不然不能对参数 赋值成功。
3、HTTPRIO1 是控件THTTPRIO。控件要设置好URL=http://fti.yndzyf.com/Service.asmx?wsdl