Using Powershell to call a WCF service method

10,659

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.

Share:
10,659
Gopalakrishnan SA
Author by

Gopalakrishnan SA

Updated on June 16, 2022

Comments

  • Gopalakrishnan SA
    Gopalakrishnan SA almost 2 years

    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)