Using Powershell to call a WCF service method
Asked Answered
V

1

6

I have a WCF service that uses wsHttpBinding with message security and clientcredentialtype as windows, and the service has a simple method

[OperationContract]
string SayHello();

public string SayHello()
    {
        return "HELLO";
    } 

<wsHttpBinding>
    <binding name="WSHttpBinding">          
      <security mode="Message">
        <message clientCredentialType="Windows" />
      </security>
    </binding>
  </wsHttpBinding>

I am trying to execute the below on powershell(version >= 2) and I get the below error

$wshttpbinding= New-WebServiceProxy -uri http://localhost:52871/Service.svc -Credential DOMAIN\gop

PS> $wshttpbinding.SayHello.Invoke()
    Exception calling "SayHello" with "0" argument(s): "The operation has timed out"
    At line:1 char:1
    + $wshttpbinding.SayHello.Invoke()
    + ~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : DotNetMethodException

However when i changed the binding to use basicHttpBinding, it works fine

<basicHttpBinding>
          <binding name="basicconfig" 
      <security mode="TransportCredentialOnly">
        <transport clientCredentialType="Windows" />
      </security>
    </binding>
</basicHttpBinding>

$basichttpbinding= New-WebServiceProxy -uri http://localhost:52871/Service.svc -Credential DOMAIN\gop

PS> $basichttpbinding.SayHello.Invoke()
HELLO   

Is there anything differently that i need to do in my script when using wsHttpBinding ?

Thanks in advance.

Final Approach I was using wsHttpBinding only for WCF transaction support. However I quickly realised that the service method call that was required to be called by the powershell script has nothing to do with transactions. Hence I exposed another BasicHttpBinding endpoint with Windows Authentication and it worked with the below script. See snippet below

Try
{
    $cred = new-object -typename System.Management.Automation.PSCredential ` -argumentlist $username, $password -ErrorAction Stop
}
Catch {
    LogWrite "Could not create PS Credential"
    $credErrorMessage = $_.Exception.Message
    LogWrite $credErrorMessage
    Break
}

Try{
    $service=New-WebServiceProxy –Uri $url -Credential $cred -ErrorAction Stop
} Catch {
    LogWrite "Could not create WebServiceProxy with $url"
    $proxyErrorMessage = $_.Exception.Message
    LogWrite $proxyErrorMessage
    Break
}

# Create Request Object
$namespace = $service.getType().namespace
$req = New-Object ($namespace + ".UpdateJobRequest")    

LogWrite "Calling service..."
$response = $service.UpdateJob($req)
Vedetta answered 8/10, 2015 at 2:43 Comment(5)
are there any other differences besides what you posted? The variable name shouldn't matter in this case. How does the method know it's wsHttpBinding or basicHttpBinding?Tomcat
are you perhaps also doing this ... $wsHttpBinding = new-object System.ServiceModel.WSHttpBindingTomcat
if that's the case, I'd debug the method call coming in on Service.scv and look at the request. Is your powershell instance logged in as you? Is it running as admin?Tomcat
Updated the post with binding information and passing credentials. I ran $wshttpbinding with the wsHttpBinding only on the config and I ran $basichttpbinding with the basichttpbinding only on the config. I passed the credential option and it prompted me to enter my windows password.Vedetta
No. i did not do $wsHttpBinding = new-object System.ServiceModel.WSHttpBindingVedetta
M
4

I've created a PowerShell module WcfPS which is available also in the gallery that helps you create in memory proxies for the targeted services using their metadata exchange. I've used this module to access services with federated security which is very heavy and difficult in the configuration, so I'm confident that it will work for you as well. There is also a blog post. All and all the module allows you to work with soap endpoints without the necessity to maintain the servicemodel configuration files and servicereferences that you usually find in a .net project.

This is an example where the $svcEndpoint holds the value of the target endpoint

  1. Probe for the metadata exchange endpoint
  2. Create the in memory types for the proxies
  3. Create an endpoint based on the imported configuration
  4. Create a channel (the proxy instance)

This is a sample code copied from the github page

$wsImporter=New-WcfWsdlImporter -Endpoint $svcEndpoint -HttpGet
$proxyType=$wsImporter | New-WcfProxyType
$endpoint=$wsImporter | New-WcfServiceEndpoint -Endpoint $svcEndpoint
$channel=New-WcfChannel -Endpoint $endpoint -ProxyType $proxyType

The module is not perfect so feel free to contribute if something is missing.

I appologize for might be perceived as incomplete answer, but this doesn't fit in a comment.

Mceachern answered 23/8, 2018 at 10:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.