Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- Added `RequestFilesLinkEnabled` and `RequestFilesLinkExpirationInDays` to the output of `Get-PnPSite` [#3557](https://github.com/pnp/powershell/pull/3557)
- Added `CoreRequestFilesLinkEnabled`, `CoreRequestFilesLinkExpirationInDays`, `OneDriveRequestFilesLinkEnabled`, `OneDriveRequestFilesLinkExpirationInDays`, `BusinessConnectivityServiceDisabled` to the output of `Get-PnPTenant` [#3557](https://github.com/pnp/powershell/pull/3557)
- Added `-BusinessConnectivityServiceDisabled` parameter to `Set-PnPTenant` cmdlt to allow disabling the Business Connectivity Service [#3562](https://github.com/pnp/powershell/pull/3562)
- Added support for executing the 'Invoke-PnPSPRestMethod' cmdlet in a batch [#3565](https://github.com/pnp/powershell/pull/3565)
- Added `Get-PnPSiteSetVersionPolicyProgress` cmdlet which allows for getting the progress of setting a version policy for existing document libraries on a site [#3564](https://github.com/pnp/powershell/pull/3564)

### Fixed
Expand Down
14 changes: 14 additions & 0 deletions documentation/Invoke-PnPSPRestMethod.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Invoke-PnPSPRestMethod -Url <String>
[-Raw]
[-Connection <PnPConnection>]
[-ResponseHeadersVariable <String>]
[-Batch <PnPBatch>]
```

## DESCRIPTION
Expand Down Expand Up @@ -79,6 +80,19 @@ This example executes a GET request towards the current site collection and retu

It will also store the response headers values in the PowerShell variable name that you specify. Enter a variable name without the dollar sign ($) symbol.

### EXAMPLE 7
```powershell
$batch = New-PnPBatch -RetainRequests
Invoke-PnPSPRestMethod -Method Get -Url "https://tenant.sharepoint.com/sites/mysite/_api/web/lists" -Batch $batch
$item = "{'Title':'Test'}"
Invoke-PnPSPRestMethod -Method Post -Url "https://tenant.sharepoint.com/sites/mysite/_api/web/lists/GetByTitle('Test')/items" -Content $item -Batch $batch
$response = Invoke-PnPBatch $batch -Details
$response
```

This example executes a GET request to get all lists and a POST request to add an item to a list in a single batch request.
It is necessary to create and invoke batch requests in the manner specified here if you want to process something later on with the response object.

## PARAMETERS

### -Content
Expand Down
77 changes: 65 additions & 12 deletions src/Commands/Base/InvokeSPRestMethod.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using Microsoft.SharePoint.Client;
using PnP.Core.Model;
using PnP.Core.Services;
using PnP.Framework.Http;
using PnP.Framework.Utilities;
using PnP.PowerShell.Commands.Enums;
using PnP.PowerShell.Commands.Model;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -16,29 +19,36 @@ namespace PnP.PowerShell.Commands.Admin
[Cmdlet(VerbsLifecycle.Invoke, "PnPSPRestMethod", DefaultParameterSetName = PARAMETERSET_Parsed)]
[OutputType(typeof(PSObject), ParameterSetName = new[] { PARAMETERSET_Parsed })]
[OutputType(typeof(string), ParameterSetName = new[] { PARAMETERSET_Raw })]
[OutputType(typeof(void), ParameterSetName = new[] { PARAMETERSET_Batch })]
public class InvokeSPRestMethod : PnPSharePointCmdlet
{
public const string PARAMETERSET_Parsed = "Parsed";
public const string PARAMETERSET_Raw = "Raw";
public const string PARAMETERSET_Batch = "Batch";

[Parameter(Mandatory = false, Position = 0, ParameterSetName = PARAMETERSET_Parsed)]
[Parameter(Mandatory = false, Position = 0, ParameterSetName = PARAMETERSET_Raw)]
[Parameter(Mandatory = false, Position = 0, ParameterSetName = PARAMETERSET_Batch)]
public HttpRequestMethod Method = HttpRequestMethod.Get;

[Parameter(Mandatory = true, Position = 0, ParameterSetName = PARAMETERSET_Parsed)]
[Parameter(Mandatory = true, Position = 0, ParameterSetName = PARAMETERSET_Raw)]
[Parameter(Mandatory = true, Position = 0, ParameterSetName = PARAMETERSET_Batch)]
public string Url;

[Parameter(Mandatory = false, ParameterSetName = PARAMETERSET_Parsed)]
[Parameter(Mandatory = false, ParameterSetName = PARAMETERSET_Raw)]
[Parameter(Mandatory = false, Position = 0, ParameterSetName = PARAMETERSET_Batch)]
public object Content;

[Parameter(Mandatory = false, ParameterSetName = PARAMETERSET_Parsed)]
[Parameter(Mandatory = false, ParameterSetName = PARAMETERSET_Raw)]
[Parameter(Mandatory = false, Position = 0, ParameterSetName = PARAMETERSET_Batch)]
public string ContentType = "application/json";

[Parameter(Mandatory = false, ParameterSetName = PARAMETERSET_Parsed)]
[Parameter(Mandatory = false, ParameterSetName = PARAMETERSET_Raw)]
[Parameter(Mandatory = false, Position = 0, ParameterSetName = PARAMETERSET_Batch)]
public string Accept = "application/json;odata=nometadata";

[Parameter(Mandatory = false, ParameterSetName = PARAMETERSET_Raw)]
Expand All @@ -48,6 +58,9 @@ public class InvokeSPRestMethod : PnPSharePointCmdlet
[Parameter(Mandatory = false, ParameterSetName = PARAMETERSET_Raw)]
public string ResponseHeadersVariable;

[Parameter(Mandatory = false, Position = 0, ParameterSetName = PARAMETERSET_Batch)]
public PnPBatch Batch;

protected override void ExecuteCmdlet()
{
if (Url.StartsWith("/"))
Expand All @@ -56,21 +69,37 @@ protected override void ExecuteCmdlet()
Url = UrlUtility.Combine(ClientContext.Url, Url);
}

var method = new HttpMethod(Method.ToString());

var httpClient = PnPHttpClient.Instance.GetHttpClient(ClientContext);
var method = new HttpMethod(Method.ToString().ToUpper());

var requestUrl = Url;

if (string.IsNullOrEmpty(Accept))
{
Accept = "application/json;odata=nometadata";
}

if (string.IsNullOrEmpty(ContentType))
{
ContentType = "application/json";
}

if (ParameterSpecified(nameof(Batch)))
{
CallBatchRequest(method, requestUrl);
}
else
{
CallSingleRequest(method, requestUrl);
}
}

private void CallSingleRequest(HttpMethod method, string requestUrl)
{
var httpClient = PnPHttpClient.Instance.GetHttpClient(ClientContext);
bool isResponseHeaderRequired = !string.IsNullOrEmpty(ResponseHeadersVariable);

using (HttpRequestMessage request = new HttpRequestMessage(method, requestUrl))
{
if (string.IsNullOrEmpty(Accept))
{
Accept = "application/json;odata=nometadata";
}

request.Headers.Add("accept", Accept);

if (Method == HttpRequestMethod.Merge)
Expand All @@ -88,10 +117,7 @@ protected override void ExecuteCmdlet()

if (Method == HttpRequestMethod.Post || Method == HttpRequestMethod.Merge || Method == HttpRequestMethod.Put || Method == HttpRequestMethod.Patch)
{
if (string.IsNullOrEmpty(ContentType))
{
ContentType = "application/json";
}

var contentString = Content is string ? Content.ToString() :
JsonSerializer.Serialize(Content, new JsonSerializerOptions() { ReferenceHandler = ReferenceHandler.IgnoreCycles, WriteIndented = true });
request.Content = new StringContent(contentString, System.Text.Encoding.UTF8);
Expand Down Expand Up @@ -150,5 +176,32 @@ protected override void ExecuteCmdlet()
}
}
}

private void CallBatchRequest(HttpMethod method, string requestUrl)
{
var web = PnPContext.Web;
string contentString = null;
if (ParameterSpecified(nameof(Content)))
{
contentString = Content is string ? Content.ToString() :
JsonSerializer.Serialize(Content, new JsonSerializerOptions() { ReferenceHandler = ReferenceHandler.IgnoreCycles, WriteIndented = true });

}

Dictionary<string, string> extraHeaders = new() { { "Accept", Accept } };

if (Method == HttpRequestMethod.Merge)
{
extraHeaders.Add("X-HTTP-Method", "MERGE");
}

if (Method == HttpRequestMethod.Merge || Method == HttpRequestMethod.Delete)
{
extraHeaders.Add("IF-MATCH", "*");
}
extraHeaders.Add("Content-Type", ContentType);

web.WithHeaders(extraHeaders).ExecuteRequestBatch(Batch.Batch, new ApiRequest(method, ApiRequestType.SPORest, requestUrl, contentString));
}
}
}