wcf - Inconsistent behavior when executing New-WebServiceProxy in a loop -
i'm having problem powershell script wrote call method on wcf web service. wcf service has composite datacontract sole request parameter. have modified servicecontract (by adding 2 new methods), new methods not being called powershell script. here original contract:
[servicecontract] public interface ifilesystemservice { [operationcontract] hashfileresponse hashfile(hashfilerequest req); [operationcontract] void generatefiles(generatefilesrequest req); }
and here new contract:
[servicecontract] public interface ifilesystemservice { [operationcontract] hashfileresponse hashfile(hashfilerequest req); [operationcontract] void generatefiles(generatefilesrequest req); [operationcontract] parsefilepathresponse parsefilepath(parsefilepathrequest req); [operationcontract] archiveparsedfileresponse archiveparsedfile(archiveparsedfilerequest req); }
the generatefiles method 1 being called powershell script. have not modified generatefilesrequest datacontract @ all, defined below:
[datacontract] public class generatefilesrequest : baserequest { [datamember(isrequired = true)] public int id { get; set; } }
baserequest empty class future use (all our request data contracts use it):
[datacontract] public abstract class baserequest { }
calling method works consistently via other means; soapui, fiddler , via wcf contracts defined throughout application.
after adding 2 new methods, our integration tests failing due fact powershell script fails call generatefiles method consistently within loop (see error output).
when wrote script, having similar issue running (though either consistently broke, or consistently worked) managed service calls working adding -namespace , -class arguments new-webserviceproxy cmdlet.
context: running powershell script on developer's machine, connecting wcf service hosted in iisexpress. developers experience same issues.
here's original script (preferred) before recent modifications (this working fine, calls fail):
$sqlserver=$args[0] function callfss($id) { $uri = "http://localhost:1234/filesystemservice.svc?wsdl" $srv = new-webserviceproxy -uri $uri -namespace fssns -class fssclass $req = [fssns.generatefilesrequest](new-object fssns.generatefilesrequest) $req.id= $id $response = $srv.generatefiles($req) } $sqlconnection = new-object system.data.sqlclient.sqlconnection $sqlconnection.connectionstring = "server=" + $sqlserver + ";database=mydatabase;integrated security=true" $sqlconnection.open() $sqlcmd = new-object system.data.sqlclient.sqlcommand $sqlcmd.commandtext = "select id mytable status = 2" $sqlcmd.connection = $sqlconnection $sqlresult = $sqlcmd.executereader() while ($sqlresult.read()) { $id = $sqlresult.getint32(0) write-host generating files id $id callfss $id } $sqlcmd.dispose() $sqlconnection.dispose() $sqlconnection.close()
here excerpt of output script. can see, vastly inconsistent (lines marked succeed):
generating files id 1 cannot convert argument "req", value: "fssns.generatefilesrequest", "generatefiles" type "fssns.generatefilesrequest": "cannot convert "fssns.generatefilesrequest" value of type "fssns.generatefilesrequest" type "fssns.generatefilesrequest"." @ c:\solutionpath\generate_files.ps1:23 char:2 + $response = $srv.generatefiles($req) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + categoryinfo : notspecified: (:) [], methodexception + fullyqualifiederrorid : methodargumentconversioninvalidcastargument generating files id 2 cannot convert argument "req", value: "fssns.generatefilesrequest", "generatefiles" type "fssns.generatefilesrequest": "cannot convert "fssns.generatefilesrequest" value of type "fssns.generatefilesrequest" type "fssns.generatefilesrequest"." @ c:\solutionpath\generate_files.ps1:23 char:2 + $response = $srv.generatefiles($req) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + categoryinfo : notspecified: (:) [], methodexception + fullyqualifiederrorid : methodargumentconversioninvalidcastargument **generating files id 3** generating files id 4 cannot convert argument "req", value: "fssns.generatefilesrequest", "generatefiles" type "fssns.generatefilesrequest": "cannot convert "fssns.generatefilesrequest" value of type "fssns.generatefilesrequest" type "fssns.generatefilesrequest"." @ c:\solutionpath\generate_files.ps1:23 char:2 + $response = $srv.generatefiles($req) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + categoryinfo : notspecified: (:) [], methodexception + fullyqualifiederrorid : methodargumentconversioninvalidcastargument generating files id 8 cannot convert argument "req", value: "fssns.generatefilesrequest", "generatefiles" type "fssns.generatefilesrequest": "cannot convert "fssns.generatefilesrequest" value of type "fssns.generatefilesrequest" type "fssns.generatefilesrequest"." @ c:\solutionpath\generate_files.ps1:23 char:2 + $response = $srv.generatefiles($req) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + categoryinfo : notspecified: (:) [], methodexception + fullyqualifiederrorid : methodargumentconversioninvalidcastargument **generating files id 9** **generating files id 10** **generating files id 11** generating files id 12 cannot convert argument "req", value: "fssns.generatefilesrequest", "generatefiles" type "fssns.generatefilesrequest": "cannot convert "fssns.generatefilesrequest" value of type "fssns.generatefilesrequest" type "fssns.generatefilesrequest"." @ c:\solutionpath\generate_files.ps1:23 char:2 + $response = $srv.generatefiles($req) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + categoryinfo : notspecified: (:) [], methodexception + fullyqualifiederrorid : methodargumentconversioninvalidcastargument
sometimes, calls pass, , odd-one fails.
here's version of script, uses auto-generated namespaces new-webserviceproxy:
$sqlserver=$args[0] function callfss($id) { $uri = "http://localhost:1234/filesystemservice.svc?wsdl" $srv = new-webserviceproxy -uri $uri $type = $srv.gettype().namespace $datatype = ($type + '.generatefilesrequest') $req = new-object($datatype) $req.id = $id $response = $srv.generatefiles($req) } $sqlconnection = new-object system.data.sqlclient.sqlconnection $sqlconnection.connectionstring = "server=" + $sqlserver + ";database=mydatabase;integrated security=true" $sqlconnection.open() $sqlcmd = new-object system.data.sqlclient.sqlcommand $sqlcmd.commandtext = "select id mytable status = 2" $sqlcmd.connection = $sqlconnection $sqlresult = $sqlcmd.executereader() while ($sqlresult.read()) { $id = $sqlresult.getint32(0) write-host generating files id $id callfss $id } $sqlcmd.dispose() $sqlconnection.dispose() $sqlconnection.close()
again, results inconsistent, though error relates auto-generated namespace:
**generating files id 1** **generating files id 2** generating files id 3 cannot convert argument "req", value: "microsoft.powershell.commands.newwebserviceproxy.autogeneratedtypes.webserviceproxy3234_filesystemservice_svc_wsdl.generatefilesrequest", "generatefiles" type "microsoft.powershell.commands.newwebserviceproxy.autogeneratedtypes.webserviceproxy3234_filesystemservice_svc_wsdl.generatefilesrequest": "cannot convert "microsoft.powershell.commands.newwebserviceproxy.autogeneratedtypes.webserviceproxy3234_filesystemservice_svc_wsdl.generatefilesrequest" value of type "microsoft.powershell.commands.newwebserviceproxy.autogeneratedtypes.webserviceproxy3234_filesystemservice_svc_wsdl.generatefilesrequest" type "microsoft.powershell.commands.newwebserviceproxy.autogeneratedtypes.webserviceproxy3234_filesystemservice_svc_wsdl.generatefilesrequest"." @ c:\solutionpath\generate_files.ps1:23 char:2 + $response = $srv.generatefiles($req) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + categoryinfo : notspecified: (:) [], methodexception + fullyqualifiederrorid : methodargumentconversioninvalidcastargument generating files id 4 cannot convert argument "req", value: "microsoft.powershell.commands.newwebserviceproxy.autogeneratedtypes.webserviceproxy3234_filesystemservice_svc_wsdl.generatefilesrequest", "generatefiles" type "microsoft.powershell.commands.newwebserviceproxy.autogeneratedtypes.webserviceproxy3234_filesystemservice_svc_wsdl.generatefilesrequest": "cannot convert "microsoft.powershell.commands.newwebserviceproxy.autogeneratedtypes.webserviceproxy3234_filesystemservice_svc_wsdl.generatefilesrequest" value of type "microsoft.powershell.commands.newwebserviceproxy.autogeneratedtypes.webserviceproxy3234_filesystemservice_svc_wsdl.generatefilesrequest" type "microsoft.powershell.commands.newwebserviceproxy.autogeneratedtypes.webserviceproxy3234_filesystemservice_svc_wsdl.generatefilesrequest"." @ c:\solutionpath\generate_files.ps1:23 char:2 + $response = $srv.generatefiles($req) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + categoryinfo : notspecified: (:) [], methodexception + fullyqualifiederrorid : methodargumentconversioninvalidcastargument + fullyqualifiederrorid : methodargumentconversioninvalidcastargument
etc... execution different every time.
i dearly hope i'm doing wrong / misunderstanding entirely give on powershell. maybe caching issue? appreciated.
ok, found :)
i added output generatefiles method definition within callfss function:
$srv | gm -name generatefiles | select -expandproperty definition
foreach successful request, output
void generatefiles(fssns.generatefilesrequest req)
the definition different if encountered error:
void generatefiles(fssns.generatefilesrequest, oehlvn0y, version=0.0.0.0, culture=neutral, publickeytoken=null req)
so if create object using full qualified name, should work:
function callfss($id) { $uri = "http://localhost:11662/service1.svc?wsdl" $srv = new-webserviceproxy -uri $uri -namespace fssns -class fssclass # definition of generatefiles method $definition = $srv | gm -name generatefiles | select -expandproperty definition # extract full qualified type name of first parameter $paramtype = [regex]::match($definition, 'generatefiles\((.*)\s\w+').groups[1].value $bar = new-object $paramtype $bar.id = $id $response = $srv.generatefiles($bar) }
note: solution works methods 1 parameter due regex. however, here implementation recommend:
function invoke-fss # invoke valid verb (see get-verb) { [cmdletbinding()] param ( [parameter(mandatory=$true,valuefrompipeline=$true,position=0)] [int]$id ) begin { $uri = "http://localhost:11662/service1.svc?wsdl" $srv = new-webserviceproxy -uri $uri -namespace fssns -class fssclass # definition of generatefiles method $definition = $srv | gm -name generatefiles | select -expandproperty definition # extract full qualified type name of first parameter $paramtype = [regex]::match($definition, 'generatefiles\((.*)\s\w+').groups[1].value } process { $bar = new-object $paramtype $bar.id = $id $response = $srv.generatefiles($bar) } end { $srv.dispose() } }
in example, invoke method piping ids invoke-ffs
method:
$ids = @() while ($sqlresult.read()) { $ids += $sqlresult.getint32(0) } $ids | invoke-fss
the begin{}
block gets called once (to initialize proxy) , process{}
block gets called each item in $ids
. finally, end{}
block gets called once @ end dispose proxy gracefully.
Comments
Post a Comment