I have a scheduled task which executes a powershell script every hour. The powershell script must make a call to a one-way WCF service operation. Essentially it just needs to
I think the problem is that the code you have is actually creating an HttpWebRequest, not a WCF request. (In other words, it's simply executing an HTTP GET request on the URL, with no SOAP or .NET Remoting information.)
You should be able to follow these instructions to create a proper endpoint:
http://msdn.microsoft.com/en-us/magazine/cc163647.aspx#S11
It should look something like this:
$httpBinding = New-Object System.ServiceModel.BasicHttpBinding
$endpointAddress = New-Object System.ServiceModel.EndpointAddress 'http://myserver.com/myservice/dosomething'
$contractDescription = [System.ServiceModel.Description.ContractDescription]::GetContract([IYourInterface], $httpBinding, $endpointAddress)
$serviceEndpoint = New-Object System.ServiceModel.Description.ServiceEndpoint $contractDescription
$channelFactory = New-Object "System.ServiceModel.ChannelFactory``1[IYourInterface]" $serviceEndpoint
$webProxy = $channelFactory.CreateChannel();
$webProxy.yourServiceMethod();
Note that you'll need to import the DLL with the IYourInterface
class for this to work:
[void] [Reflection.Assembly]::LoadFrom('path/to/your.dll')
Alternatively, if you have a WSDL defined for the service, you can follow these much easier instructions to access the service:
http://blogs.technet.com/heyscriptingguy/archive/2009/11/17/hey-scripting-guy-november-17-2009.aspx
Alternatively alternatively, you can figure out what the HTTP SOAP request needs to look like, and form it yourself within the HttpWebRequest
.
HTTP replay approach:
You don't have to use WCF to call a WCF service, you can mimic one with 3-4 changes from HTTP defaults. Just don't try to building the SOAP envelope yourself. But it's safe to replay everything you need from Fiddler over 'plain' HTTP.
I like jdmichal's answer because it is intuitive to make it work for inputs where the parameters are objects... the code required some modifications, this is what worked for me:
[Reflection.Assembly]::LoadFrom("C:\.....\WcfService2.dll")
[Reflection.Assembly]::LoadWithPartialName("System.ServiceModel")
$httpBinding = New-Object System.ServiceModel.BasicHttpBinding
if($useNTLM){
#passes the default creds
$httpBinding.Security.Mode = "TransportCredentialOnly"
$httpBinding.Security.Transport.ClientCredentialType = "Ntlm"
}
$endpointAddress = New-Object System.ServiceModel.EndpointAddress 'http://localhost:63600/Service1.svc'
$contractDescription = [System.ServiceModel.Description.ContractDescription]::GetContract([WcfService2.IService1])
$serviceEndpoint = New-Object System.ServiceModel.Description.ServiceEndpoint($contractDescription, $httpBinding, $endpointAddress)
$channelFactory = New-Object "System.ServiceModel.ChannelFactory``1[WcfService2.IService1]"($serviceEndpoint)
$webProxy = $channelFactory.CreateChannel();
$result = $webProxy.GetData(123);
Write-Output $result #prints 123
$comptype = new-object WcfService2.CompositeType
$comptype.BoolValue =$false
$comptype.StringValue = "whatever123zxcv"
$result = $webProxy.GetDataUsingDataContract($comptype);
Write-Output $result #prints whatever123zxcv
UPDATE: I've found out how to use composite objects with the New-WebServiceProxy cmdlet (thanks to http://www.sqlmusings.com/2012/02/04/resolving-ssrs-and-powershell-new-webserviceproxy-namespace-issue/)
$wsProxy = New-WebServiceProxy -uri http://localhost:63600/Service1.svc
$wsProxy.UseDefaultCredentials = $true
$namespace = $wsProxy.GetType().Namespace
$myct = New-Object "$namespace.CompositeType"
$myct.BoolValue = $true;
$myct.StringValue = "asdfasdg";
$wsProxy.GetDataUsingDataContract($myct)
$wsProxy.GetData(123,$true)
PowerShell 2.0 makes this trivial with the New-WebServiceProxy cmdlet e.g.:
$zip = New-WebServiceProxy -uri http://www.webservicex.net/uszip.asmx?WSDL
$zip.getinfobyzip(20500).table
CITY : Washington
STATE : DC
ZIP : 20500
AREA_CODE : 202
TIME_ZONE : E
I believe that you'll need to set the HTTP method first before attempting to get a response. By default, I believe the WebRequest object defaults to POST, but you'll actually need to set it to GET.
I haven't used PowerShell scripting much, but based off of your sample it would look something like this:
$request = [System.Net.WebRequest]::Create("http://myserver.com/myservice/dosomething")
$request.Method = "GET"
$request.GetResponse()
Hope that helps!