homotechsual / HaloAPI

PowerShell module for the Halo Service Solutions series of software products.
MIT License
48 stars 38 forks source link

[Bug]: JSON array error on new ticket creation #21

Closed FarazUSL closed 3 months ago

FarazUSL commented 1 year ago

Contact Details

Faraz.Shaukat@upsher-smith.com

What happened?

First time trying the New-HaloTicket Module. Have the latest module and running PS 7.3.0 I can create user + assets correctly but when i try a new ticket I get the following. Guessing i am missing something syntax wise but when i pass variables similar to Set-HaloAsset for example seems to work fine.

Appreciate any guidance \ example for the right way to create this :)

Version

1.0.1

Which operating systems have you tested on?

What PowerShell version are you running?

7.2.0-preview.8

Halo Product

Halo ISTM

Halo Version

2.104.4

What command did you run?

PS C:\Windows\System32> $tickettype = @([pscustomobject]@{id="61"})
PS C:\Windows\System32> $assetType = "142"
PS C:\Windows\System32> #$affectedAsset = @([pscustomobject]@{inventory_number="FBSPJT2"})
PS C:\Windows\System32> $affectedAsset = @([pscustomobject]@{id="3945"})
PS C:\Windows\System32> $asgnUser = @([pscustomobject]@{id="33"})
PS C:\Windows\System32> $haloSiteId = "18"
PS C:\Windows\System32>
PS C:\Windows\System32> $ticketArray =@()
PS C:\Windows\System32>
PS C:\Windows\System32>     $tabEntry = New-Object PSObject
PS C:\Windows\System32>     $tabEntry | Add-Member Noteproperty tickettype      $tickettype
PS C:\Windows\System32>     $tabEntry | Add-Member Noteproperty assets         $affectedAsset
PS C:\Windows\System32>     $tabEntry | Add-Member Noteproperty user            $asgnUser
PS C:\Windows\System32>     $tabEntry | Add-Member Noteproperty site_id         $haloSiteId
PS C:\Windows\System32>     $ticketArray += $tabEntry
PS C:\Windows\System32> $ticketArray

tickettype assets       user       site_id
---------- ------       ----       -------
{@{id=61}} {@{id=3945}} {@{id=33}} 18

PS C:\Windows\System32> new-HaloTicket -Ticket $ticketArray -Verbose

What was the output of the command?

VERBOSE: Building parameters for New-HaloTicket. Use '-Debug' with '-Verbose' to see parameter values as they are built.
VERBOSE: Performing the operation "Create" on target "Tickets".
VERBOSE: Building [HttpQSCollection] for New-HaloGETRequest
VERBOSE: Making a POST request to https://usldev.haloitsm.com:443/api/tickets?cf=&wi=
VERBOSE: HTTP/1.1 POST with 228-byte payload
VERBOSE: received 1238-byte response of content type application/json
VERBOSE: Generating Halo error output.
VERBOSE: ErrorDetails contained in error record.
VERBOSE: ErrorDetails is JSON.
VERBOSE: ErrorDetails is not null.
New-HaloError: C:\Users\user1234\Documents\PowerShell\Modules\HaloAPI\1.11.1\Public\New\New-HaloTicket.ps1:40
Line |
  40 |          New-HaloError -ErrorRecord $_
     |          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The Halo API said {"[0].user":["Cannot deserialize the current JSON array (e.g. [1,2,3]) into type
     | 'HaloClassLibrary.Models.Users' because the type requires a JSON object (e.g. {\"name\":\"value\"}) to deserialize
     | correctly.\r\nTo fix this error either change the JSON to a JSON object (e.g. {\"name\":\"value\"}) or change the
     | deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that
     | can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a
     | JSON array.\r\nPath '[0].user', line 13, position 13."],"[0].tickettype":["Cannot deserialize the current JSON array
     | (e.g. [1,2,3]) into type 'HaloClassLibrary.Models.RequestType' because the type requires a JSON object (e.g.
     | {\"name\":\"value\"}) to deserialize correctly.\r\nTo fix this error either change the JSON to a JSON object (e.g.
     | {\"name\":\"value\"}) or change the deserialized type to an array or a type that implements a collection interface (e.g.
     | ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the
     | type to force it to deserialize from a JSON array.\r\nPath '[0].tickettype', line 3, position 19."]}. The API returned
     | the following HTTP error response: 400 Bad Request
PS C:\Windows\System32>
sullymanmanmanamn commented 1 year ago

$ticketArray =@() vs $ticketArray = @{}

also - below may be simpler to work with?

$ValidAction = @{ tickettype = 61 affectedAsset = 3945 assettype = 142 user = 33 site_id = 18 }

$tickettype = $ValidAction.tickettype $assetType = $ValidAction.assettype $affectedAsset = $ValidAction.affectedAsset $asgnUser = $ValidAction.user $haloSiteId = $ValidAction.site_id

homotechsual commented 1 year ago

Yes your issue here is that you're using an array for user, ticket type and affectedAsset when they aren't array type values. Use the suggestion from @sullymanmanmanamn and just assign those properties the integer values directly :-)

FarazUSL commented 1 year ago

thanks for the feedback @sullymanmanmanamn & @homotechsual .

-So I have been trying to pass "PSobjects" with attributes that match the fields that are being returned and how they are populated. And seems to be working :). For the "Set-HaloAsset" I was only able to get a "user" assignment to work when I used "$asgnUser = @([pscustomobject]@{id="29"})" instead of "$asgnUser = "29"" in the psobject.

PS C:\Windows\System32> set-HaloAsset -Asset $updateHaloAsset New-HaloError: C:\Users\user\Documents\PowerShell\Modules\HaloAPI\1.11.1\Public\Set\Set-HaloAsset.ps1:41 Line | 41 | New-HaloError -ErrorRecord $_ | ~~~~~~~~~ | The Halo API said {"[0].users":["Error converting value \"29\" to type 'HaloClassLibrary.Models.Users_List[]'. Path | '[0].users', line 4, position 17."]}. The API returned the following HTTP error response: 400 Bad Request


PS C:\Windows\System32> $ValidAction = @{

tickettype = 61 affectedAsset = 3945 assettype = 142 user = 33 site_id = 18 } PS C:\Windows\System32> PS C:\Windows\System32> $tickettype = $ValidAction.tickettype PS C:\Windows\System32> $assetType = $ValidAction.assettype PS C:\Windows\System32> $affectedAsset = $ValidAction.affectedAsset PS C:\Windows\System32> $asgnUser = $ValidAction.user PS C:\Windows\System32> $haloSiteId = $ValidAction.site_id PS C:\Windows\System32> $ticketArray =@() PS C:\Windows\System32> PS C:\Windows\System32> $tabEntry = New-Object PSObject PS C:\Windows\System32> $tabEntry | Add-Member Noteproperty tickettype $tickettype PS C:\Windows\System32> $tabEntry | Add-Member Noteproperty assets $affectedAsset PS C:\Windows\System32> $tabEntry | Add-Member Noteproperty user $asgnUser PS C:\Windows\System32> $tabEntry | Add-Member Noteproperty site_id $haloSiteId PS C:\Windows\System32> $ticketArray += $tabEntry PS C:\Windows\System32> $validAction

Name Value


assettype 142 affectedAsset 3945 tickettype 61 site_id 18 user 33

PS C:\Windows\System32> $ticketArray

tickettype assets user site_id


    61   3945   33      18

PS C:\Windows\System32> new-HaloTicket -Ticket $ticketArray -Verbose VERBOSE: Building parameters for New-HaloTicket. Use '-Debug' with '-Verbose' to see parameter values as they are built. VERBOSE: Performing the operation "Create" on target "Tickets". VERBOSE: Building [HttpQSCollection] for New-HaloGETRequest VERBOSE: Making a POST request to https://usldev.haloitsm.com:443/api/tickets?cf=&wi= VERBOSE: HTTP/1.1 POST with 94-byte payload VERBOSE: received 393-byte response of content type application/json VERBOSE: Generating Halo error output. VERBOSE: ErrorDetails contained in error record. VERBOSE: ErrorDetails is JSON. VERBOSE: ErrorDetails is not null. New-HaloError: C:\Users\user1234\Documents\PowerShell\Modules\HaloAPI\1.11.1\Public\New\New-HaloTicket.ps1:40 Line | 40 | New-HaloError -ErrorRecord $_ | ~~~~~~~~~ | The Halo API said {"[0].user":["Error converting value 33 to type 'HaloClassLibrary.Models.Users'. Path '[0].user', line 5, | position 14."],"[0].assets":["Error converting value 3945 to type 'HaloClassLibrary.Models.Device_List[]'. Path | '[0].assets', line 4, position 18."],"[0].tickettype":["Error converting value 61 to type | 'HaloClassLibrary.Models.RequestType'. Path '[0].tickettype', line 3, position 20."]}. The API returned the following HTTP | error response: 400 Bad Request


PS C:\Windows\System32> $ValidAction

Name Value


assettype 142 affectedAsset 3945 tickettype 61 site_id 18 user 33

PS C:\Windows\System32> new-HaloTicket -Ticket $ValidAction -Verbose VERBOSE: Building parameters for New-HaloTicket. Use '-Debug' with '-Verbose' to see parameter values as they are built. VERBOSE: Performing the operation "Create" on target "Tickets". VERBOSE: Building [HttpQSCollection] for New-HaloGETRequest VERBOSE: Making a POST request to https://usldev.haloitsm.com:443/api/tickets?cf=&wi= VERBOSE: HTTP/1.1 POST with 124-byte payload VERBOSE: received 259-byte response of content type application/json VERBOSE: Generating Halo error output. VERBOSE: ErrorDetails contained in error record. VERBOSE: ErrorDetails is JSON. VERBOSE: ErrorDetails is not null. New-HaloError: C:\Users\user1234\Documents\PowerShell\Modules\HaloAPI\1.11.1\Public\New\New-HaloTicket.ps1:40 Line | 40 | New-HaloError -ErrorRecord $_ | ~~~~~~~~~ | The Halo API said {"[0].user":["Error converting value 33 to type 'HaloClassLibrary.Models.Users'. Path '[0].user', line 7, | position 14."],"[0].tickettype":["Error converting value 61 to type 'HaloClassLibrary.Models.RequestType'. Path | '[0].tickettype', line 5, position 20."]}. The API returned the following HTTP error response: 400 Bad Request

Thanks again for your time & help

homotechsual commented 1 year ago

So for those "object" properties the syntax would be:

assignedUser = @{ id = 1 }

The issue you're facing is that you're casting it explicitly to an array () of objects [PSCustomObject]@{} whereas a simple hashtable object @{} is sufficient.

FarazUSL commented 1 year ago

just thought of that too and was trying it when got your response :) Unfortunately, seem to be getting the same result again. For the "Set-HaloAsset" I was able to resolve the error by using this syntax #$asgnUser = @([pscustomobject]@{id="29"})

Am I just building this object wrong :( i.e. are there other required attributes that need to be part of this object before it can be sent over to the function that I am missing?

PS C:\Windows\System32> $tickettype = @{id=61} PS C:\Windows\System32> $affectedAsset = @{id=3945} PS C:\Windows\System32> $asgnUser = @{id=33} PS C:\Windows\System32> $haloSiteId = "18" PS C:\Windows\System32> PS C:\Windows\System32> $ticketArray =@() PS C:\Windows\System32> PS C:\Windows\System32> $tabEntry = New-Object PSObject PS C:\Windows\System32> $tabEntry | Add-Member Noteproperty tickettype $tickettype PS C:\Windows\System32> $tabEntry | Add-Member Noteproperty assets $affectedAsset PS C:\Windows\System32> $tabEntry | Add-Member Noteproperty user $asgnUser PS C:\Windows\System32> $tabEntry | Add-Member Noteproperty siteid $haloSiteId PS C:\Windows\System32> $ticketArray += $tabEntry PS C:\Windows\System32> new-HaloTicket -Ticket $ticketArray -Verbose VERBOSE: Building parameters for New-HaloTicket. Use '-Debug' with '-Verbose' to see parameter values as they are built. VERBOSE: Performing the operation "Create" on target "Tickets". VERBOSE: Building [HttpQSCollection] for New-HaloGETRequest VERBOSE: Making a POST request to https://usldev.haloitsm.com:443/api/tickets?cf=&wi= VERBOSE: HTTP/1.1 POST with 162-byte payload VERBOSE: received 646-byte response of content type application/json VERBOSE: Generating Halo error output. VERBOSE: ErrorDetails contained in error record. VERBOSE: ErrorDetails is JSON. VERBOSE: ErrorDetails is not null. New-HaloError: C:\Users\usl-shaukafa\Documents\PowerShell\Modules\HaloAPI\1.11.1\Public\New\New-HaloTicket.ps1:40 Line | 40 | New-HaloError -ErrorRecord $ | ~~~~~~~~~ | The Halo API said {"[0].assets.id.assets":["Cannot deserialize the current JSON object (e.g. {\"name\":\"value\"}) into | type 'HaloClassLibrary.Models.Device_List[]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize | correctly.\r\nTo fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so | that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that | can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a | JSON object.\r\nPath '[0].assets.id', line 7, position 11."]}. The API returned the following HTTP error response: 400 Bad | Request

BTW - This might be nothing but, came across the following - https://stackoverflow.com/questions/22557559/cannot-deserialize-the-json-array-e-g-1-2-3-into-type-because-type-requ ""Your json string is wrapped within square brackets ([]), hence it is interpreted as array""

Looking at the debug, the body does seem to be wrapped in ' [ ] ' .. .not sure if this has anything to do with what seeing.

VERBOSE: Building [HttpQSCollection] for New-HaloGETRequest DEBUG: Request body: [ { "tickettype": { "id": 61 }, "assets": { "id": 3945 }, "user": { "id": 33 }, "site_id": "18" } ] VERBOSE: Making a POST re

homotechsual commented 1 year ago

Here's an example of changing the user on a ticket:

Set-HaloTicket -Ticket @{ id = 18; user = @{ id = 40 } }

Or on an asset:

Set-HaloAsset -Asset @{ id = 11; users = ,@{ id = 40 } }

Where prefixing users = ,@{} with the comma is a cheat to tell PowerShell to consider the value an array. The fuller syntax would be:

Set-HaloAsset -Asset @{ id = 11; users = @(@{ id = 40 }) }

You only need to force a property value to an array if it expects an array and you definitely don't need to build PSCustomObjects all the time - simple hashtables are more than sufficient :-)

FarazUSL commented 1 year ago

Ok ... progress... Seems like the affected asset needed the @([pscustomobject]@{id="3945"})...while the other two didn't :) I was warned by the API at the point that Details and Category were required.

This time it did successfully create a ticket ... BUT not of the ticket Type identified for the id :(

$tickettype = @{id="61"} $affectedAsset = @([pscustomobject]@{id="3945"}) $asgnUser = @{id="33"} $haloSiteId = "18" $details = "PowerShell Halo Ticket" $TicketCategory = "Hardware>Laptop"

$ticketArray =@()

$tabEntry = New-Object PSObject 
$tabEntry | Add-Member Noteproperty tickettype      $tickettype
$tabEntry | Add-Member Noteproperty assets          $affectedAsset
$tabEntry | Add-Member Noteproperty user            $asgnUser
$tabEntry | Add-Member Noteproperty site_id         $haloSiteId
$tabEntry | Add-Member Noteproperty details         $details
$tabEntry | Add-Member Noteproperty category_1      $TicketCategory
$ticketArray += $tabEntry 

PS C:\Windows\System32> new-HaloTicket -Ticket $ticketArray[0] -Verbose -Debug VERBOSE: Building parameters for New-HaloTicket. Use '-Debug' with '-Verbose' to see parameter values as they are built. DEBUG: Found Switch param DEBUG: Adding parameter wi with value DEBUG: Excluding system parameter InformationAction. DEBUG: Found Switch param DEBUG: Adding parameter cf with value DEBUG: Excluding system parameter PipelineVariable. DEBUG: Excluding system parameter OutBuffer. DEBUG: Excluding system parameter Verbose. DEBUG: Excluding system parameter OutVariable. DEBUG: Excluding system parameter Debug. DEBUG: Excluding system parameter WarningAction. DEBUG: Excluding system parameter ErrorAction. DEBUG: Excluding system parameter InformationVariable. DEBUG: Found Switch param ReturnAll DEBUG: Skipping unset param ReturnAll DEBUG: Excluding system parameter ErrorVariable. DEBUG: Excluding system parameter WarningVariable. DEBUG: Query collection contains Name Value


cf wi

Confirm Are you sure you want to perform this action? Performing the operation "Create" on target "Tickets". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): A DEBUG: Query string in New-HaloGETRequest contains: Name Value


cf wi

VERBOSE: Building [HttpQSCollection] for New-HaloGETRequest DEBUG: Request body: [ { "tickettype": { "id": "61" }, "assets": [ { "id": "3945" } ], "user": { "id": "33" }, "site_id": "18", "details": "PowerShell Halo Ticket", "category_1": "Hardware>Laptop" } ] VERBOSE: Making a POST request to https://usldev.haloitsm.com:443/api/tickets?cf=&wi= VERBOSE: HTTP/1.1 POST with 268-byte payload VERBOSE: received 54121-byte response of content type application/json DEBUG: Response headers: Key Value


Date {Fri, 11 Nov 2022 15:21:45 GMT} Connection {keep-alive} Cache-Control {no-store, must-revalidate, no-cache} Location {http://usldev.haloitsm.com/api/Tickets/2892} Server {Microsoft-IIS/10.0} Request-Context {appId=cid-v1:592cbe01-3c3f-49a6-921a-9e08ca3f94e5} Strict-Transport-Security {max-age=31536000; IncludeSubDomains} Content-Type {application/json; charset=utf-8} Content-Length {54121}

FarazUSL commented 1 year ago

OK "explicitly" setting "$tickettypeid = "61"" & "$asgnUserid = "33"" is giving me the Ticket that I want :D

At this point seems like the "assigned asset" is "not known" fast enough in the ticket generation process for the Halo "$ALLASSETS" variable to populate the ticket summary and information in the default details $ALLFIELDS table...but the Custom Assest Field of that asset does populate which is interesting.

$tickettype = @{id="61"} $tickettypeid = "61" $affectedAsset = @([pscustomobject]@{id="3945"}) $asgnUser = @{id="33"} $asgnUserid = "33" $haloSiteId = "18" $details = "$ALLFIELDS MDT Build Date?$AFBF-MDTBuildDate Affected System: $ALLASSETS" $summary = "Project:$ASSETTYPE Refresh - `$ALLASSETS" $TicketCategory = "Hardware>Laptop"

$ticketArray =@()

$tabEntry = New-Object PSObject 
$tabEntry | Add-Member Noteproperty tickettype      $tickettype
$tabEntry | Add-Member Noteproperty tickettype_id   $tickettypeid
$tabEntry | Add-Member Noteproperty assets          $affectedAsset
$tabEntry | Add-Member Noteproperty user            $asgnUser
$tabEntry | Add-Member Noteproperty user_id         $asgnUserid
$tabEntry | Add-Member Noteproperty site_id         $haloSiteId
$tabEntry | Add-Member Noteproperty details         $details
$tabEntry | Add-Member Noteproperty category_1      $TicketCategory
$tabEntry | Add-Member Noteproperty summary         $summary
$ticketArray += $tabEntry

I think with the syntax understanding this should be "SOLVED' :) thanks for your help, time, guidance etc. @homotechsual & @sullymanmanmanamn.... Wil reach out if anything weird comes up