2
votes

After attempting several different examples I am unable to update list items using the Sharepoint REST API. I receive back a 400 error from the request.

The creplace is due to Sharepoint sending both ID and Id for some reason and breaking the ConvertFrom-Json in my Get-SPListItems method.

function Update-SPListItems
{
    param
    (
        $listUpdate
    )
    $requestDigest = Get-RequestDigest

    foreach($item in $listUpdate.Results)
    {
        $restUrl = $item.__metadata.uri
        $item.tsFeedbackStatus = "Open"
        $item.Modified = Get-Date -Format s

        $updatedItem = $item | ConvertTo-Json
        #convert back the duplicate field
        $updatedItem = $updatedItem -creplace '"ignoreId":','"Id":'

        $itemJsonBytes = [System.Text.Encoding]::ASCII.GetBytes($updatedItem)
        try 
         {
            #examples have shown POST/MERGE, POST/PATCH, MERGE/MERGE,
            #PATCH/PATCH, none of them in those combinations have worked
            $request = [System.Net.WebRequest]::Create($restUrl)
            $request.Credentials = $Credential.GetNetworkCredential()
            $request.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")
            $request.Headers.Add("If-Match", "*")
            $request.Headers.Add("X-RequestDigest", $requestDigest)
            $request.Headers.Add("X-HTTP-Method", "MERGE")
            $request.Accept = "application/json;odata=verbose" 
            $request.Method = "POST"
            $request.ContentType = "application/json;odata=verbose" 
            $request.ContentLength = $itemJsonBytes.Length
            $stream = $request.GetRequestStream()
            $stream.Write($itemJsonBytes, 0, $itemJsonBytes.Length)
            $stream.Close()

            $response = $request.GetResponse()
        }
        catch [System.Exception]
        {
            Write-Error $_.Exception.ToString()        
        }

    }
}

Here is the exact error:

Update-SPListItems : System.Net.WebException: The remote server returned an error: (400) Bad Request.

at System.Net.HttpWebRequest.GetResponse()

at CallSite.Target(Closure , CallSite , Object )

At C:\Users\user\Desktop\SPListTest.ps1:120 char:11

  • $result = Update-SPListItems $list

  • ~~~~~~~~~~~~~~~~~~~~~~~~

  • CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException

  • FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Update-SPListItems

1
I'd try posting this at sharepoint.stackexchange.com - Aziz Kabyshev

1 Answers

0
votes

Try the below reusable function for this. It worked for me every time. Ensure to pass the parameters properly. This has authentication built into it and even works for older versions of PowerShell.

function Request-Rest{    
    [CmdletBinding()]
    PARAM (
        [Parameter(Mandatory=$False)]
        [String]$Metadata,

        [Parameter(Mandatory=$true)]
        [String] $URL,

        [Parameter(Mandatory=$False)]
        [Switch]$listUpdate,

        [Parameter(Mandatory=$False)]
        [String]$RequestDigest,

        [Parameter(Mandatory=$false)]
        [Microsoft.SharePoint.Client.SharePointOnlineCredentials] $credentials,

        [Parameter(Mandatory=$false)]
        [String] $UserAgent = "PowerShell API Client",

        [Parameter(Mandatory=$false)]
        [Switch] $JSON,

        [Parameter(Mandatory=$false)]
        [Switch] $Raw
    )
    #Create a URI instance since the HttpWebRequest.Create Method will escape the URL by default.   
    #$URL = Fix-Url $Url
    $URI = New-Object System.Uri($URL,$true)   

    #Create a request object using the URI   
    $request = [System.Net.HttpWebRequest]::Create($URI)   

    #Build up a User Agent   
    $request.UserAgent = $(   
        "{0} (PowerShell {1}; .NET CLR {2}; {3})" -f $UserAgent, $(if($Host.Version){$Host.Version}else{"1.0"}),  
        [Environment]::Version,  
        [Environment]::OSVersion.ToString().Replace("Microsoft Windows ", "Win")  
        )

    if ($credentials -eq $null)
    {
        $request.UseDefaultCredentials = $true
    }
    else
    {
        $request.Credentials = $credentials
    }

    $request.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")

    #Request Method
    $request.Method = "POST"

    #Headers
    if($listUpdate)
    {
        $request.Headers.Add("X-RequestDigest", $RequestDigest)
        $request.Headers.Add("If-Match", "*")
        $request.Headers.Add("X-HTTP-Method", "MERGE")

        $request.ContentType = "application/json;odata=verbose"
        $request.Accept = "application/json;odata=verbose"
    }

    #Request Body
    if($Metadata) {  
        $Body = [byte[]][char[]]$Metadata   
        $request.ContentLength = $Body.Length 

        $stream = $request.GetRequestStream()
        $stream.Write($Body, 0, $Body.Length)
    }
    else {
        $request.ContentLength = 0
    }


    try
    {
        [System.Net.HttpWebResponse] $response = [System.Net.HttpWebResponse] $request.GetResponse()
    }
    catch
    {
            Throw "Exception occurred in $($MyInvocation.MyCommand): `n$($_.Exception.Message)"
    }

    $reader = [IO.StreamReader] $response.GetResponseStream()  

    if (($PSBoundParameters.ContainsKey('JSON')) -or ($PSBoundParameters.ContainsKey('Raw')))
    {
        $output = $reader.ReadToEnd()  
    }
    else
    {
        $output = $reader.ReadToEnd()  
    }

    $reader.Close()  

    if($output.StartsWith("<?xml"))
    {
        [xml]$outputXML = [xml]$output
    }
    else
    {
        [xml]$outputXML = [xml] ("<xml>" + $output + "</xml>")
    }

    Write-Output $outputXML 

    $response.Close()
}