Mr Bees
Mr Bees

Reputation: 11

Powershell/XML saving returned value and multiple scripts

I've written XML code to open a ticket in Autotask and inserted it into a PowerShell script because it needs to be automated. The script creates a ticket and I need to save a value that the create ticket function returns so I can then update it in the same script. Is there a way to

  1. run a create ticket HTTP POST request subsequently followed by an update request in the same script, and
  2. somewhere in between the scripts save the value <id></id> that is returned by the create ticket script, and then use it as a variable in the update ticket script?
$RequestBody = @"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Header>
    <AutotaskIntegrations xmlns="http://autotask.net/ATWS/v1_5/">
    </AutotaskIntegrations>
  </soap:Header>
  <soap:Body>
    <create xmlns="http://autotask.net/ATWS/v1_5/">
      <Entities>
        <Entity xsi:type="Ticket" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        all my entities
        </Entity>
      </Entities>
    </create>
  </soap:Body>
</soap:Envelope>
"@

Invoke-WebRequest -Uri $AUTOTASK -Method Post -Body $RequestBody -ContentType $ContentType -UseBasicParsing -Headers $Headers;

$id = @"<id/>"@  # The field I want to save and insert later is returned as <id></id>

$UpdateBody = @"
<?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:Header>
    <AutotaskIntegrations xmlns="http://autotask.net/ATWS/v1_5/">
    </AutotaskIntegrations>
  </soap:Header>
  <soap:Body>
    <update xmlns="http://autotask.net/ATWS/v1_5/">
      <Entities>
        <Entity xsi:type="Ticket" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
           all my entities
           <id>$id</id>
        </Entity>
      </Entities>
    </update>
  </soap:Body>
</soap:Envelope>
"@

Invoke-WebRequest -Uri $AUTOTASK -Method Post -Body $UpdateBody -ContentType $ContentType -UseBasicParsing -Headers $Headers;

The headers were left out on purpose due to them containing sensitive info.

EDIT: Here is the response to the request:

<soap:Envelope
  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
>
  <soap:Body>
    <createResponse xmlns="http://autotask.net/ATWS/v1_5/">
      <createResult>
        <ReturnCode>1</ReturnCode>
        <EntityResults>
          <Entity xsi:type="Ticket">
            <id>12345</id>
            <UserDefinedFields> 
              <UserDefinedField><Name>Escalated Internally?</Name></UserDefinedField>
              <UserDefinedField><Name>Ticket Category</Name></UserDefinedField>
              <UserDefinedField><Name>Escalated by Customer?</Name></UserDefinedField>
              <UserDefinedField><Name>Initial Severity</Name></UserDefinedField>
              <UserDefinedField><Name>Incident Start Date/Time</Name></UserDefinedField>
            </UserDefinedFields> 
          </Entity>
          <!-- etc. -->
        </EntityResults>
      </createResult>
    </createResponse>
  </soap:Body>
</soap:Envelope>

It's just a giant block of fields. In there is a field called <id></id> whose value is an integer, which is what I need.

EDIT 2:
Updated Code

$RequestBody = @"
<?xml version="1.0" encoding="utf-8"?>

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Header>
    <AutotaskIntegrations xmlns="http://autotask.net/ATWS/v1_5/">
    </AutotaskIntegrations>
  </soap:Header>
  <soap:Body>
    <create xmlns="http://autotask.net/ATWS/v1_5/">
      <Entities>
        <Entity xsi:type="Ticket" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <AccountID>123</AccountID>
          <Active>123</Active>
          <DueDateTime>09/30/18</DueDateTime>
          <Title>$Title</Title>
          <Status>123</Status>
          <Priority>123</Priority>
          <QueueID>123<QueueID>
          <InstalledProductID>123</InstalledProductID>
         </Entity>
      </Entities>
    </create>
  </soap:Body>
</soap:Envelope>
"@

$rsp = Invoke-WebRequest -Uri $AUTOTASK -Method Post -Body $RequestBody -ContentType $ContentType -UseBasicParsing -Headers $Headers;
$ticketno = $rsp.ResponseXml.Envelope.Body.createResponse.createResult.EntityResults.Entity.id;

$UpdateBody = @"
<?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:Header>
    <AutotaskIntegrations xmlns="http://autotask.net/ATWS/v1_5/">
    </AutotaskIntegrations>
  </soap:Header>
  <soap:Body>
    <update xmlns="http://autotask.net/ATWS/v1_5/">
      <Entities>
        <Entity xsi:type="Ticket" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          <AccountID>123</AccountID>
          <Title>Success</Title>
          <Status>123</Status>
          <Priority>123</Priority>
          <id>$ticketno</id>
          <DueDateTime>09/30/18</DueDateTime>
          <QueueID>123</QueueID>
        </Entity>
      </Entities>
    </update>
  </soap:Body>
</soap:Envelope>
"@

Invoke-WebRequest -Uri $AUTOTASK -Method Post -Body $UpdateBody -ContentType $ContentType -UseBasicParsing -Headers $Headers;

Error response:

Invoke-WebRequest : soap:ClientSystem.Web.Services.Protocols.SoapException:
Server was unable to read request. ---> System.InvalidOperationException:
There is an error in XML document (15, 20). ---> System.FormatException:
Input string was not in a correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt64(String value, NumberStyles options, NumberFormatInfo numfmt)
   at System.Int64.Parse(String s, NumberStyles style, IFormatProvider provider)
   at System.Xml.XmlConvert.ToInt64(String s)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read201_Ticket(Boolean isNullable, Boolean checkType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read5_Entity(Boolean isNullable, Boolean checkType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read253_update()
   at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer44.Deserialize(XmlSerializationReader reader)
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)
   at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
   --- End of inner exception stack trace ---
   at System.Web.Services.Protocols.SoapServerProtocol.ReadParameters()
   at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()
At C:\Users\Marc\Documents\StoredValue.ps1:86 char:1
+ Invoke-WebRequest -Uri $AUTOTASK -Method Post -Body $UpdateBody -Cont ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     + CategoryInfo          : InvalidOperation: (Method: POST, R...pe: text/xml}:HttpRequestMessage) [Invoke-WebRequest], HttpResponseException
     + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

EDIT 3:

Result of $rsp | Get-Member

       TypeName: Microsoft.PowerShell.Commands.BasicHtmlWebResponseObject

Name              MemberType Definition
----              ---------- ----------
Equals            Method     bool Equals(System.Object obj)
GetHashCode       Method     int GetHashCode()
GetType           Method     type GetType()
ToString          Method     string ToString()
BaseResponse      Property   System.Net.Http.HttpResponseMessage BaseResponse {get;set;}
Content           Property   string Content {get;}
Encoding          Property   System.Text.Encoding Encoding {get;}
Headers           Property   System.Collections.Generic.Dictionary[string,System.Collections.Generic.IEnumerable[string]] Headers {get;}
Images            Property   Microsoft.PowerShell.Commands.WebCmdletElementCollection Images {get;}
InputFields       Property   Microsoft.PowerShell.Commands.WebCmdletElementCollection InputFields {get;}
Links             Property   Microsoft.PowerShell.Commands.WebCmdletElementCollection Links {get;}
RawContent        Property   string RawContent {get;set;}
RawContentLength  Property   long RawContentLength {get;}
RawContentStream  Property   System.IO.MemoryStream RawContentStream {get;}
RelationLink      Property   System.Collections.Generic.Dictionary[string,string] RelationLink {get;}
StatusCode        Property   int StatusCode {get;}
StatusDescription Property   string StatusDescription {get;}

Upvotes: 0

Views: 871

Answers (1)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200473

You can select the ID from the response XML with a simple XPath query. Note that you need a namespace manager, though, because the XML data has namespaces. I thought the response had a property ResponseXml with the already parsed XML data, but that doesn't seem to be the case, so you probably need something like this:

$rsp = Invoke-WebRequest -Uri $AUTOTASK -Method Post -Body $RequestBody ...
[xml]$xml = $rsp.Content
$nm = New-Object Xml.XmlNamespaceManager $xml.NameTable
$nm.AddNamespace('ns', 'http://autotask.net/ATWS/v1_5/')
$id = $xml.SelectSingleNode('//ns:id', $nm).'#text'

You could also use dot-access, which in this particular scenario is probably the simpler approach, because it bypasses namespaces and auto-expands the value of the leaf node:

$rsp = Invoke-WebRequest -Uri $AUTOTASK -Method Post -Body $RequestBody ...
[xml]$xml = $rsp.Content
$id = $xml.Envelope.Body.createResponse.createResult.EntityResults.Entity.id

Upvotes: 1

Related Questions