Using Powershell to call a WCF service method

Gopalakrishnan SA picture Gopalakrishnan SA · Oct 8, 2015 · Viewed 9.7k times · Source

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)

Answer

Alex Sarafian picture Alex Sarafian · Aug 23, 2018

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.