Solved

New-WebServiceProxy passing sessionId to SOAP header

Posted on 2013-12-05
2
2,569 Views
Last Modified: 2016-02-26
Ok, I'm dieing here.  Somebody help me out please.  Here's what I have going on:

I am trying to design a Powershell script that will connect to salesforce and retrieve information.  The script I have so far will allow me to connect to the salesforce API and login, and it returns a sessionId in "$sf.loginResponse.SessionId".  I want to take this session ID and insert it into the session header so that I can run API calls.  Here is what I have so far:

$URI = "[insert-full-path-to-file]\salesforce-api-partner.wsdl"
$username = "michael1@desktopninjas.com"
$password = "testtest171XKd4g57k4KFgXHk7QbK8Kc7"

$sf = New-WebServiceProxy -Uri $URI -Namespace sf -UseDefaultCredential
$sf
$LoginResponse = $sf.login($username, $password)
$LoginResponse
$newSession = $LoginResponse.sessionId
$newSession
$newURL = $LoginResponse.serverUrl
$sf.Url = $newURL
$sf.Url
$sf.SessionHeaderValue.sessionId = $newSession
$soapQuery = $sf.query("SELECT Name FROM Lead")
$sf.logout()

Open in new window


Yes, I know there a password in there.  This is just a developer account.  There's no sensitive info in it and I'll change it once we fix this.  

This script gives me the following errors in Powershell ISE 3.0:

The property 'sessionId' cannot be found on this object. Verify that the property exists and can be set.
At C:\Users\mlucas\Dropbox\Desktop Ninjas\Clients\CCC\powershell-dev\0.1\soap-request2.ps1:20 char:1
+ $sf.SessionHeaderValue.sessionId = $newSession
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFound
 
Exception calling "query" with "1" argument(s): "INVALID_SESSION_ID: Invalid Session ID found in SessionHeader: Illegal Session"
At C:\Users\mlucas\Dropbox\Desktop Ninjas\Clients\CCC\powershell-dev\0.1\soap-request2.ps1:21 char:1
+ $soapQuery = $sf.query("SELECT Name FROM Lead")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : SoapException
 
Exception calling "logout" with "0" argument(s): "INVALID_SESSION_ID: Invalid Session ID found in SessionHeader: Illegal Session"
At C:\Users\mlucas\Dropbox\Desktop Ninjas\Clients\CCC\powershell-dev\0.1\soap-request2.ps1:22 char:1
+ $sf.logout()
+ ~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : SoapException

Open in new window


I've tried to add-member but I'll not very good at it and I can't figure it out.  If anyone can help me with this step I will reward generously.  I've attached the script and WSDL file (in text format) for your review.
salesforce-api-partner.wsdl.txt
soap-request2.ps1.txt
0
Comment
Question by:orther
  • 2
2 Comments
 

Author Comment

by:orther
ID: 39699422
It seems like using the defined namespace "#sf.Url" or #loginResponse.sessionId" I am able to add them to variables and process them, but anything to do with the header doesn't stick.  If you look in the SOAP envelope for query(), you'll see that the envelope is not expecting the sessionId in the body, but in the header.  There's something I'm missing here.

This envelope actually works from SOAP-UI to pull data:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:partner.soap.sforce.com">
   <soapenv:Header>
      <urn:SessionHeader>
         <urn:sessionId>00Di0000000iRH2!AQoAQL2N1aUx8D8j3ViQ.7lV0qcxIAZmsG3SEy9wfIz9saCKw4DXWZIeD5Yl8V52_2.7cBNMyw6bvlycbB4r0VxIZ5VVfT9H</urn:sessionId>
      </urn:SessionHeader>
   </soapenv:Header>
   <soapenv:Body>
      <urn:query>
         <urn:queryString>SELECT Email FROM Lead WHERE Name = 'Michael Lucas'</urn:queryString>
      </urn:query>
   </soapenv:Body>
</soapenv:Envelope>

Open in new window


Comes back as this:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="urn:partner.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sf="urn:sobject.partner.soap.sforce.com">
   <soapenv:Header>
      <LimitInfoHeader>
         <limitInfo>
            <current>789</current>
            <limit>5000</limit>
            <type>API REQUESTS</type>
         </limitInfo>
      </LimitInfoHeader>
   </soapenv:Header>
   <soapenv:Body>
      <queryResponse>
         <result xsi:type="QueryResult">
            <done>true</done>
            <queryLocator xsi:nil="true"/>
            <records xsi:type="sf:sObject">
               <sf:type>Lead</sf:type>
               <sf:Id xsi:nil="true"/>
               <sf:Email>michael@desktopninjas.com</sf:Email>
            </records>
            <size>1</size>
         </result>
      </queryResponse>
   </soapenv:Body>
</soapenv:Envelope>

Open in new window

0
 

Accepted Solution

by:
orther earned 0 total points
ID: 39703965
OK, great bunch of help you guys are.  ;-)  Just kidding.  Here's what I came up with:

Instead of trying to add the sessionID into the object pipeline for New-WebServiceProxy, I decided to go a different route and use Invoke-WebRequest to send pre-built SOAP envelopes stored in here-strings.  The full code is below.  For those of you who are trying to connect powershell to Salesforce, this is the best way, trust me.  Powershell handles XML like a champ!  Just pipes the XML response right into an Object collection and you can start working with it.

# Set some variables (need to pipe these in from config.xml later in development)
$URI = "C:\Users\mlucas\Dropbox\Desktop Ninjas\Clients\CCC\powershell-dev\0.1\salesforce-api-partner.wsdl"
$username = "[omitted]"
$password = "[omitted]

# New-WebServiceProxy to call login() through salesforce API
write-progress -activity "Connecting to SalesForce API" -status "10% Complete:" -percentcomplete 10;
$service = New-WebServiceProxy -Uri $URI -Namespace service -UseDefaultCredential

write-progress -activity "Pulling Variables" -status "25% Complete:" -percentcomplete 25;
# grab LoginResponse and pull sessionId and serverUrl for the next calls
$LoginResponse = $service.login($username, $password)
$sessionID = $LoginResponse.sessionId
$newURL = $LoginResponse.serverUrl

write-progress -activity "Building Functions" -status "50% Complete:" -percentcomplete 50;
# build function to call query() in salesforce API
function Call-SFQuery([string]$sessionID, [string]$query1, [string]$newURL)
{
$queryBody = [xml] @"
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:partner.soap.sforce.com">
   <soapenv:Header>
      <urn:SessionHeader>
         <urn:sessionId>$sessionID</urn:sessionId>
      </urn:SessionHeader>
   </soapenv:Header>
   <soapenv:Body>
      <urn:query>
         <urn:queryString>$query1</urn:queryString>
      </urn:query>
   </soapenv:Body>
</soapenv:Envelope>
"@

Invoke-WebRequest $newURL -Method Post -Headers @{SOAPAction=$newURL} -ContentType "text/xml" -Body $queryBody
}

# build function to call logout() in salesforce API
function Call-SFLogout([string]$sessionID)
{
$queryBody = [xml] @"
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:partner.soap.sforce.com">
   <soapenv:Header>
      <urn:SessionHeader>
         <urn:sessionId>$sessionID</urn:sessionId>
      </urn:SessionHeader>
   </soapenv:Header>
   <soapenv:Body>
      <urn:logout/>
   </soapenv:Body>
</soapenv:Envelope>
"@

Invoke-WebRequest $newURL -Method Post -Headers @{SOAPAction=$newURL} -ContentType "text/xml" -Body $queryBody
}

# Set query and pipe to XML enabled variable so it sets it up in object collection
write-progress -activity "Executing Query" -status "80% Complete:" -percentcomplete 80;
$query1 = "SELECT Name, Email From Lead"
[xml]$response = Call-SFQuery $sessionID $query1 $newURL

# set some variable from 
$records = $response.Envelope.Body.queryResponse.result.records
$names = $response.Envelope.Body.queryResponse.result.records.name
$emails = $response.Envelope.Body.queryResponse.result.records.email

# call logout (optional at this point)
write-progress -activity "Logging Out" -status "100% Complete:" -percentcomplete 100;
$logoutReturn = Call-SFLogout $sessionID

# one way to work with the data
$names | Format-Table -Property name,email

# for each loop using object collections as data.
$records | ForEach-Object {
$_.name
$_.email
}

Open in new window

0

Featured Post

Zoho SalesIQ

Hassle-free live chat software re-imagined for business growth. 2 users, always free.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Search on a site 5 92
Microsoft Audit question 13 57
Setting strict transport security header in header not working 1 78
Is COM supported from Apache 1 44
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
We need a new way to communicate time sensitive or critical info.   The best part of my role at xMatters is visiting our clients all over the world to learn about how they operate their businesses, share insights that xMatters has gleaned across…
Learn how to set-up PayPal payment integration in your Wufoo form. Allow your users to remit payment through PayPal upon completion of your online form. This is helpful for collecting membership payments, customer payments, donations, and more.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

911 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now