Skip to content

Commit

Permalink
Merge pull request #3565 from gautamdsheth/feature/1644
Browse files Browse the repository at this point in the history
Feature #1644 : Add support for batch requests in
  • Loading branch information
KoenZomers authored Nov 14, 2023
2 parents 52302fc + d5f24e0 commit 2eec12b
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 12 deletions.
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));
}
}
}

0 comments on commit 2eec12b

Please sign in to comment.