Powershell Salesforce SOAP API SessionHeader Type

2019-07-15 10:11发布

问题:

Hi I am having trouble setting the SessionHeaderValue. I am basing my code on c#.Net. The login works and I receive the serviceUrl and sessionId in the login result but I can't get the session Id set in the session header

Here is the code

$uri = "c:\installs\sforce.wsdl"
$username = "username"
$password = "password"
# Proxy
$service = New-WebServiceProxy -Uri $uri -Namespace sforce -UseDefaultCredential
# Login
$loginResult = $service.login($username, $password)
$service.Url = $loginResult.serverUrl
$service.SessionHeaderValue = New-Object sforce.SessionHeader

This is the error I get which is a bit odd.

Exception setting "SessionHeaderValue": "Cannot convert the "sforce.SessionHeader" value of type "sforce.SessionHeader" to type "sforce.SessionHeader"."

I have been playing with this for a few hours now and have run out of ideas.

Any help is appreciated.

Anthony

回答1:

The real problem is that you can't reuse $service. Your instance of $service is only good for the login, and that's it. I think it's due to the way New-WebServiceProxy works. Check this little script out:

$uri = 'file://C:\projects\CRM\SalesForce\Integration\enterprise.xml'
$api = new-webserviceproxy -uri $uri -NameSpace SalesForce

$api.GetType().Module.Assembly.ManifestModule.ScopeName

$api = new-object SalesForce.SforceService.ScopeName
$api.GetType().Module.Assembly.ManifestModule

If you were to run this script, (of course you'd need to substitute your own WSDL), you'd see something like this (the DLLs are dynamic, so the names will be different):

mhgl0l5w.dll 
vzecopaq.dll

Notice that not only are the object references for $api different, but the dynamic assembly that New-WebServiceProxy creates is different for each one, which isn't what you might expect. That's why your cast is failing; your objects with the same name are different because they come from different dynamic assemblies. I'm not sure why the behavior is this way - if it's a peculiarity of New-WebServiceProxy, or somehow in SalesForce's WSDL.

The solution is actually pretty simple. Recreate your service object off the namespace generated by New-WebServiceProxy like so:

$uri = "c:\installs\sforce.wsdl"
$username = "username"
$password = "password"
# Proxy
$service = New-WebServiceProxy -Uri $uri -Namespace sforce -UseDefaultCredential

# Login
$loginResult = $service.login($username, $password)

$service = New-Object sforce.SforceService
$service.Url = $loginResult.serverUrl
$service.SessionHeaderValue = New-Object sforce.SessionHeader


回答2:

I found a webpage that implies the the $service.SessionHeaderValue instance should be created using something like:

$service.SessionHeaderValue = New-ObjectFromProxy -proxy $service -proxyAttributeName "SessionHeaderValue" -typeName "SessionHeader"

There was a definition for the New-ObjectFromProxy function in PowerShell + SOAP + AuthenticationInfoValue:

function New-ObjectFromProxy {
    param($proxy, $proxyAttributeName, $typeName)

    # Locate the assembly for $proxy
    $attribute = $proxy | gm | where { $_.Name -eq $proxyAttributeName }
    $str = "`$assembly = [" + $attribute.TypeName + "].assembly"
    invoke-expression $str

    # Instantiate an AuthenticationHeaderValue object.
    $type = $assembly.getTypes() | where { $_.Name -eq $typeName }

    return $assembly.CreateInstance($type)
}

I don't profess to be a powershell expert, but it appears the instance of the object that New-Object creates isn't really the same type that the proxy object is expecting. Confusingly, they do have the same name.



回答3:

Exception setting "SessionHeaderValue": "Cannot convert the "sforce.SessionHeader" value of type "sforce.SessionHeader" to type "sforce.SessionHeader"."

$service.SessionHeaderValue = New-Object sforce.SessionHeader

After New-Object you have to specify the correct class name. Try this:

#Login to Salesforce
$loginResults = $service.login($username,$password)

#set the session Id in partner Object 
$service.Url = $loginResults.serverUrl
$sessionHeaderObjClassName = ($service.GetType().FullName) -replace "SforceService","SessionHeader"
$service.SessionHeaderValue = New-Object $sessionHeaderObjClassName
$service.SessionHeaderValue.sessionId = $loginResults.sessionId