Hi i need a help with proper soap request. I tried few ways do it but no luck.
Need to generate such soap request:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Header><Action xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:env="http://www.w3.org/2003/05/soap-envelope" env:mustUnderstand="true"/><MessageID xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing">uuid:..............</MessageID><ReplyTo xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing"><Address>http://www.w3.org/2004/08/addressing/anonymous</Address></ReplyTo><To xmlns="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:env="http://www.w3.org/2003/05/soap-envelope" env:mustUnderstand="true">host_url</To><wsse:Security xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" env:mustUnderstand="true"><wsse:UsernameToken><wsse:Username xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">$login</wsse:Username><wsse:Password xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" wsse:Type="http://docs.oas
is-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">$password</wsse:Password></wsse:UsernameToken></wsse:Security></soap:Header>
<soap:Body>
................
</soap:Body>
</soap:Envelope>
i stucked on this getting iis internal error 500:
(...)
write-host "Sending SOAP Request To Server: $URL"
$soapWebRequest = [System.Net.WebRequest]::Create($URL)
$soapWebRequest.Headers.Add("SOAPAction","`"MethodName`"")
$soapWebRequest.ContentType = "application/soap+xml;charset=`"utf-8`";action=`"host/MethodName`""
$soapWebRequest.Method = "POST"
write-host "Initiating Send."
$requestStream = $soapWebRequest.GetRequestStream()
$SOAPRequest.Save($requestStream)
$requestStream.Close()
write-host "Send Complete, Waiting For Response."
$resp = $soapWebRequest.GetResponse()
$responseStream = $resp.GetResponseStream()
$soapReader = [System.IO.StreamReader]($responseStream)
$ReturnXml = [Xml] $soapReader.ReadToEnd()
$responseStream.Close()
write-host "Response Received."
return $ReturnXml
}
$url = 'host.asmx'
$soap = [xml]#"
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:flow="host">
<soap:Header/>
<soap:Body>
.....
</soap:Body>
</soap:Envelope>
"#
$ret = Execute-SOAPRequest $soap $url; $ret | Export-Clixml "test-$(Get-date -f yyyy-MM-dd-mm-ss).xml";
Your headers seem odd mixing up escaped quotes you actually don't need.
Try replacing
$soapWebRequest.Headers.Add("SOAPAction","`"MethodName`"")
by
$soapWebRequest.Headers.Add("SOAPAction","MethodName")
as well as
$soapWebRequest.ContentType = "application/soap+xml;charset=`"utf-8`";action=`"host/MethodName`""
by
$soapWebRequest.ContentType = "application/soap+xml; charset=utf-8";
Related
I'm attempting to test this section of a PowerShell function:
# post
$Response = Invoke-WebRequest -Method POST -Uri $Uri -Body $Body -ContentType 'application/xml'
# parse Response.Content; return as System.Xml.XmlDocument
[xml]$Response.Content
by mocking the BasicHtmlWebResponseObject that is returned by Invoke-WebRequest:
Mock Invoke-WebRequest {
$WebResponse = [System.Net.HttpWebResponse]::new()
[System.Net.HttpWebResponse].GetField('m_StatusCode', 'NonPublic, Instance').SetValue(
$WebResponse,
200,
'NonPublic,SetField',
$null,
(Get-Culture)
)
$Content = '<?xml version="1.0" encoding="UTF-8"?><response><control>failure<status></status></control><operation><result><status>failure</status></result></operation></response>'
$Response = [Microsoft.PowerShell.Commands.BasicHtmlWebResponseObject]::new($WebResponse,$Content)
return $Response
}
This assertion fails because I'm not creating the HttpWebResponse or BasicHtmlWebResponseObject correctly:
It "returns the response's Content object" {
# act
$Content = Send-Request -Session $Session
# assert
Assert-MockCalled Invoke-WebRequest
$Content | Should -BeOfType [xml]
$Content.response.control.status | Should -Be 'success'
$Content.response.operation.result.status | Should -Be 'success'
}
** edit **
I thought about using New-MockObject:
Mock Invoke-WebRequest {
$Response = New‐MockObject -Type Microsoft.PowerShell.Commands.BasicHtmlWebResponseObject
$Response.Content = '<?xml version="1.0" encoding="...'
}
but, the Content property is read-only.
** /edit **
What am I missing?
A slightly simpler alternative might be to wrap your invoke-webrequest in a function and just mock that instead. E.g.
function Get-XmlFromUri
{
param( $Uri, $Method, $Body )
$Response = Invoke-WebRequest -Method $Method -Uri $Uri -Body $Body -ContentType 'application/xml’
[xml]$Response.Content
}
Now you can mock Get-XmlFromUri and just return a System.Xml.XmlDocument object from hard-coded xml, which is much easier to create than a BasicHtmlWebResponseObject that needs reflection calls spin up.
Mock Get-XmlFromUri {
[xml] '<?xml version="1.0" encoding="UTF-8"?>
<response>
<control><status>success</status></control>
<operation><result><status>success</status></result></operation>
</response>'
}
Or, depending on how much like BasicHtmlWebResponseObject your code needs it to be, you can just return a hashtable from your invoke-webrequest mock that has the properties you need:
Mock Invoke-WebRequest {
new-object pscustomobject -property #{
Content = '<?xml version="1.0" encoding="UTF-8"?>
<response>
<control><status>success</status></control>
<operation><result><status>success</status></result></operation>
</response>’
}
}
(apologies for code formatting - currently typing one handed on an iPhone at 4 AM holding a not-very-sleepy baby :-S)
On PowerShell Core this doesn't work for me:
[System.Net.HttpWebResponse].GetField('m_StatusCode', 'NonPublic, Instance')
And thats why your Mock isn't returning what you expect. That line does work on Windows PowerShell however. Not sure what the right equivalent is on PSCore, needs research but thought i'd get you this far in the meantime.
This works:
Mock Invoke-WebRequest {
$Response = New-MockObject -Type Microsoft.PowerShell.Commands.BasicHtmlWebResponseObject
$Content = `
'<?xml version="1.0" encoding="UTF-8"?>
<response>
<control><status>success</status></control>
<operation><result><status>success</status></result></operation>
</response>'
$Response | Add-Member -NotePropertyName Content -NotePropertyValue $Content -Force
$Response
}
I am trying to retrieve data from a SOAP web service using PowerShell. I am having issues retrieving values from the inner XML. The code is listed below.
In the [XML]$body2 variable if I pass the $queryid variable then the values in the else condition of the Response function does not print. I debugged the code and $queryid is getting the correct value. If I remove $queryid and replace it with a number then the values print fine.
Edit: The $queryid should be set to a number which I then want to use in $body2.
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$id1 = "1"
$id2 = "2"
$global:queryid = ""
$array = #()
function Main() {
$uri = "https://mywebsite/CatalogTasks.asmx?WSDL"
[XML]$body = #"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope">
<soap:Body>
<Request xmlns="http://mywebsite.com">
<user>user_id</user>
<pwd>password</pwd>
<fields>[Number],Tech name],[Description],[State]</fields>
<condition>[State]='Open'</condition>
<orderBy>[Number]</orderBy>
</Request>
</soap:Body>
</soap:Envelope>
"#
Response $uri $body $id1
Write-Host "Id: $global:queryid"
$queryid = $global:queryid
[XML]$body2 = #"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope">
<soap:Body>
<RetrieveXML xmlns="http://mywebsite.com">
<user>user_id</user>
<pwd>password</pwd>
<queryId>$queryid</queryId>
</RetrieveXML>
</soap:Body>
</soap:Envelope>
"#
Response $uri $body2 $id2
}
function Response ($url, $bodyy, $id) {
$resp = (Invoke-WebRequest -Uri $url -Body $bodyy -ContentType "text/xml" -Proxy "http://proxy" -ProxyUseDefaultCredentials -Method POST)
if ($id -eq 1) {
$soap = $resp.Content
$xpathfilter = "//*[local-name()='QueryId']"
$Element = Select-Xml -Content $soap -XPath $xpathfilter
$global:queryid = $Element.Node.'#text'
} else {
$soap2 = $resp.Content
$filter = "//*[local-name()='Number']"
$Element2 = Select-Xml -Content $soap2 -XPath $filter
$number = $Element2.Node.'#text'
[array]$array = ($number)
foreach ($i in $array){
Write-Host $i
}
}
}
Main
I need to make a Soap Request from Powershell, I am on Powershell 2.0, I can find lots of examples but I also need to include a username and password to get through the api.
I get a response of
Exception calling "GetResponse" with "0" argument(s): "The underlying connectio
n was closed: An unexpected error occurred on a send."
My Powershell code (I have redacted some sensitive stuff) is
function Execute-SOAPRequest
(
[Xml] $SOAPRequest,
[String] $URL
)
{
write-host "Sending SOAP Request To Server: $URL"
$soapWebRequest = [System.Net.WebRequest]::Create($URL)
$soapWebRequest.Headers.Add("SOAPAction","`"`"")
$soapWebRequest.ContentType = "text/xml;charset=`"utf-8`""
$soapWebRequest.Accept = "text/xml"
$soapWebRequest.Method = "POST"
$username = "USERNAME"
$password = "Password" | ConvertTo-SecureString -asPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($username,$password)
$soapWebRequest.Credentials = $cred
#$soapWebRequest.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
#$soapWebRequest.UseDefaultCredentials = $true
write-host $soapWebRequest
write-host "Initiating Send."
$requestStream = $soapWebRequest.GetRequestStream()
write-host $requestStream
$SOAPRequest.Save($requestStream)
$requestStream.Close()
write-host "Send Complete, Waiting For Response."
$resp = $soapWebRequest.GetResponse()
$responseStream = $resp.GetResponseStream()
$soapReader = [System.IO.StreamReader]($responseStream)
$ReturnXml = [Xml] $soapReader.ReadToEnd()
$responseStream.Close()
write-host "Response Received."
return $ReturnXml
}
$url = 'https://zkncsavia049.via.novonet:7180/ws/activeservices/pmspapi_nomination'
$soap = [xml]#'
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:pms="http://www.mydomain.co.uk/pmsapi_nomination" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wssu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soapenv:Header><wsse:Security><wsse:UsernameToken wssu:Id="UsernameToken-4B81F4838BB6D8A60715299310629901"><wsse:Username>igyadmin</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">V3rm0nt</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">x9DSipKzGHLbvyCOXKIY6A==</wsse:Nonce>
<wssu:Created>2018-06-25T12:51:02.986Z</wssu:Created></wsse:UsernameToken></wsse:Security>
</soapenv:Header>
<soapenv:Body>
<pms:pmsapi_nomination.getlist.ApiRequest xmlns:ns2="http://www.mydomain.co.uk/pmsapi_nomination">
<ApiRequest>
<LogonInfo>
<BusinessGroup>GMP</BusinessGroup>
<AdminGroup>ADMN</AdminGroup>
</LogonInfo>
<BUSINESS_GROUP>
<value>GMP</value>
</BUSINESS_GROUP>
<CONTEXT>
<value>F</value>
</CONTEXT>
<REFNO>
<value>0039760</value>
</REFNO>
</ApiRequest>
</pms:pmsapi_nomination.getlist.ApiRequest>
</soapenv:Body>
</soapenv:Envelope>
'#
$ret = Execute-SOAPRequest $soap $url
I can get the call to work through SOAPUI the raw XML is
POST http://zkncsavia049.via.novonet:7180/ws/activeservices/pmsapi_nomination/HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: ""
Content-Length: 1541
Host: zkncsavia049.via.novonet:7180
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
<soapenv:Envelope xmlns:pms="http://www.mydomain.co.uk/pmsapi_nomination" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wssu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<soapenv:Header><wsse:Security><wsse:UsernameToken wssu:Id="UsernameToken-78C15367B2B1287BB3153000735070610"><wsse:Username>USERNAME</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password><wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">q5B6XRmHsecmHouCqH03qA==</wsse:Nonce><wssu:Created>2018-06-26T10:02:30.696Z</wssu:Created></wsse:UsernameToken></wsse:Security>
</soapenv:Header>
<soapenv:Body>
<pms:pmsapi_nomination.getlist.ApiRequest xmlns:ns2="http://www.aquilauk.co.uk/pmsapi_nomination">
<ApiRequest>
<LogonInfo>
<BusinessGroup>GMP</BusinessGroup>
<AdminGroup>ADMN</AdminGroup>
</LogonInfo>
<BUSINESS_GROUP>
<value>GMP</value>
</BUSINESS_GROUP>
<CONTEXT>
<value>F</value>
</CONTEXT>
<REFNO>
<value>0039761</value>
</REFNO>
</ApiRequest>
</pms:pmsapi_nomination.getlist.ApiRequest>
</soapenv:Body>
</soapenv:Envelope>
There is an SSL certificate on the system but not for port 7180.
I'm also very much a powershell novice, I only write it a couple of times a year.
So the fail is on
$resp = $soapWebRequest.GetResponse()
but I guess that the setting up of $soapWebRequest may be the problem
I am using the following powershell script to send xml data stored in a text file (soap.txt) to an endpoint.
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("charset", 'utf-8')
$headers.Add("SOAPAction", 'nms:rtEvent#PushEvent')
Invoke-WebRequest http://localhost:8080/nl/jsp/soaprouter.jsp -Method Post -ContentType 'text/xml' -Headers $headers -InFile D:\Scripts\archive\soap.txt
Whilst the above method works fine, I wish to use the -Body param instead so that I can enrich the content but I am facing some issues, below is the code.
## Set SOAP headers
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("charset", 'utf-8')
$headers.Add("SOAPAction", 'nms:rtEvent#PushEvent')
$url = "http://localhost:8080/nl/jsp/soaprouter.jsp"
$body = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:nms:rtEvent">
<soapenv:Header/>
<soapenv:Body>
...etc etc
</soapenv:Body>
</soapenv:Envelope>'
Invoke-WebRequest -Method Post -Uri $url -Headers $headers -Body $body -ContentType 'application/xml'
I am getting the following error
I've also tried
$body = #"
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:nms:rtEvent">
<soapenv:Header/>
<soapenv:Body>
...rest of code here asd
</soapenv:Body>
</soapenv:Envelope>
"#
Invoke-WebRequest -Method Post -Uri $url -ContentType 'text/xml' -Headers $headers -Body $body
And i get that the header must be modified using the appropiate property or method, so I append the content type also to the header but that doesn't work either, I am using powershell 3.0
The answer is to remove the XML indentation in the variable, is this issue documented somewhere? or is it a limitation.
$body = #"
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:nms:rtEvent">
<soapenv:Header/>
<soapenv:Body>
...rest of code here asd
</soapenv:Body>
</soapenv:Envelope>
"#
I try to utilise the code example. But I am unsuscessful. Can any one pick up an error? (I know about New-WebServiceProxy cmdlet.)
function Execute-SOAPRequest
(
[Xml] $SOAPRequest,
[String] $URL
)
{
write-host “Sending SOAP Request To Server: $URL”
$soapWebRequest = [System.Net.WebRequest]::Create($URL)
$soapWebRequest.Headers.Add("SOAPAction" ,"http://www.webservicex.net/globalweather.asmx?WSDL/GetWeather")
$soapWebRequest.ContentType = 'text/xml;charset="utf-8"'
$soapWebRequest.Accept = “text/xml”
$soapWebRequest.Method = “POST”
write-host “Initiating Send.”
$requestStream = $soapWebRequest.GetRequestStream()
$SOAPRequest.Save($requestStream)
$requestStream.Close()
write-host “Send Complete, Waiting For Response.”
$resp = $soapWebRequest.GetResponse()
$responseStream = $resp.GetResponseStream()
$soapReader = [System.IO.StreamReader]($responseStream)
$ReturnXml = [Xml] $soapReader.ReadToEnd()
$responseStream.Close()
write-host “Response Received.”
return $ReturnXml
}
function Execute-SOAPRequestFromFile
(
[String] $SOAPRequestFile,
[String] $URL
)
{
write-host “Reading and converting file to XmlDocument: $SOAPRequestFile”
$SOAPRequest = [Xml](Get-Content $SOAPRequestFile)
return $(Execute-SOAPRequest $SOAPRequest $URL)
}
$x = Execute-SOAPRequestFromFile -SOAPRequestFile soap-W.txt -URL "http://www.webservicex.net/globalweather.asmx?WSDL"
The file soap-W.txt:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.webserviceX.NET" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope">
<SOAP-ENV:Body>
<tns:GetWeather xmlns:tns="http://www.webserviceX.NET">
<tns:CityName>Tampa</tns:CityName>
<tns:CountryName>United States</tns:CountryName>
</tns:GetWeather>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Server return error 500. Query via New-WebServiceProxy is successfull.
You should try New-WebServiceProxy CmdLet.
$svc = New-WebServiceProxy -Uri "http://www.webservicex.net/globalweather.asmx?WSDL"
$svc.GetWeather("Aurillac", "France")