diff --git a/CHANGELOG.md b/CHANGELOG.md index 47243686b..a8017f476 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). ### Changed - Updated implementation of `Move-PnPFile` to now also support moving of files and folders accross site collections [PR #2749](https://github.com/pnp/PnP-PowerShell/pull/2749) - Fixed issue where using `Disconnect-PnPOnline -Connection $variable` after having connected using `$variable = Connect-PnPOnline -CertificatePath -ReturnConnection`, it would not clean up the certificate on that connection instance passed in by $variable, but instead try to do it on the current connection context [PR #2755](https://github.com/pnp/PnP-PowerShell/pull/2755) +- Fixed `Invoke-PnPSPRestMethod -Method Merge` not passing in the `If-Match: *` header and thereby causing failed requests [PR #2764](https://github.com/pnp/PnP-PowerShell/pull/2764) - If a certain PnP PowerShell cmdlet needs access to the SharePoint Admin Center site in order to function correctly, it will now list this in the Synopsis section of the Get-Help for the cmdlet - Fixed issue where using `Connect-PnPOnline` using `-Thumbnail` would delete the private key on some devices when running `Disconnect-PnPOnline` [PR #2759](https://github.com/pnp/PnP-PowerShell/pull/2759) - Updated test project structure [PR #2767](https://github.com/pnp/PnP-PowerShell/pull/2767) diff --git a/Commands/Base/InvokeSPRestMethod.cs b/Commands/Base/InvokeSPRestMethod.cs index 06ce08c1a..dc6e0f0f2 100644 --- a/Commands/Base/InvokeSPRestMethod.cs +++ b/Commands/Base/InvokeSPRestMethod.cs @@ -49,18 +49,17 @@ public class InvokeSPRestMethod : PnPSharePointCmdlet [Parameter(Mandatory = false, Position = 0, HelpMessage = "The Http method to execute. Defaults to GET.")] public HttpRequestMethod Method = HttpRequestMethod.Get; - [Parameter(Mandatory = true, Position = 0, HelpMessage = "The url to execute.")] + [Parameter(Mandatory = true, Position = 0, HelpMessage = "The url to execute")] public string Url; [Parameter(Mandatory = false, HelpMessage = "A string or object to send")] public object Content; - [Parameter(Mandatory = false, HelpMessage = "The content type of the object to send. Defaults to 'application/json'")] + [Parameter(Mandatory = false, HelpMessage = "The content type of the object to send. Defaults to 'application/json'.")] public string ContentType = "application/json"; protected override void ExecuteCmdlet() { - if (Url.StartsWith("/")) { // prefix the url with the current web url @@ -70,16 +69,14 @@ protected override void ExecuteCmdlet() var accessToken = this.ClientContext.GetAccessToken(); var method = new HttpMethod(Method.ToString()); - //var method = new HttpMethod(Method.ToString().ToUpper()); - using (var handler = new System.Net.Http.HttpClientHandler()) + using (var handler = new HttpClientHandler()) { // we're not in app-only or user + app context, so let's fall back to cookie based auth - if (String.IsNullOrEmpty(accessToken)) + if (string.IsNullOrEmpty(accessToken)) { SetAuthenticationCookies(handler, ClientContext); } - using (var httpClient = new PnPHttpProvider(handler)) { var requestUrl = Url; @@ -94,9 +91,14 @@ protected override void ExecuteCmdlet() request.Headers.Add("X-HTTP-Method", "MERGE"); } + if (Method == HttpRequestMethod.Merge || Method == HttpRequestMethod.Delete) + { + request.Headers.Add("IF-MATCH", "*"); + } + if (!string.IsNullOrEmpty(accessToken)) { - request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken); + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); } else { @@ -105,7 +107,7 @@ protected override void ExecuteCmdlet() handler.Credentials = networkCredential; } } - request.Headers.Add("X-RequestDigest", (ClientContext as ClientContext).GetRequestDigest().GetAwaiter().GetResult()); + request.Headers.Add("X-RequestDigest", ClientContext.GetRequestDigest().GetAwaiter().GetResult()); if (Method == HttpRequestMethod.Post) { @@ -140,7 +142,6 @@ protected override void ExecuteCmdlet() } } } - } private void SetAuthenticationCookies(HttpClientHandler handler, ClientContext context) @@ -175,7 +176,6 @@ private void SetAuthenticationCookies(HttpClientHandler handler, ClientContext c } } - //Taken from "Remote Authentication in SharePoint Online Using the Client Object Model" //https://code.msdn.microsoft.com/Remote-Authentication-in-b7b6f43c @@ -202,7 +202,6 @@ internal static class CookieReader /// Returns Cookie contents as a string public static string GetCookie(string url) { - int size = 512; StringBuilder sb = new StringBuilder(size); if (!NativeMethods.InternetGetCookieEx(url, null, sb, ref size, INTERNET_COOKIE_HTTPONLY, IntPtr.Zero)) @@ -222,7 +221,6 @@ public static string GetCookie(string url) private static class NativeMethods { - [DllImport("wininet.dll", EntryPoint = "InternetGetCookieEx", CharSet = CharSet.Unicode, SetLastError = true)] public static extern bool InternetGetCookieEx( string url,