/// <summary> /// Updates the expiration datetime (and notification URL) of an existing SharePoint web hook /// </summary> /// <param name="webUrl">Url of the site holding resource with the webhook</param> /// <param name="resourceType">The type of Hookable SharePoint resource</param> /// <param name="resourceId">Id of the resource (e.g. list id)</param> /// <param name="subscriptionId">Id of the web hook subscription that we need to delete</param> /// <param name="webHookEndPoint">Url of the web hook service endpoint (the one that will be called during an event)</param> /// <param name="expirationDateTime">New web hook expiration date</param> /// <param name="accessToken">Access token to authenticate against SharePoint</param> /// <param name="context">ClientContext instance to use for authentication</param> /// <exception cref="ArgumentOutOfRangeException">Thrown when expiration date is out of valid range.</exception> /// <returns>true if succesful, exception in case something went wrong</returns> public static async Task <bool> UpdateWebhookSubscriptionAsync(string webUrl, WebHookResourceType resourceType, string resourceId, string subscriptionId, string webHookEndPoint, DateTime expirationDateTime, string accessToken, ClientContext context) { if (!ValidateExpirationDateTime(expirationDateTime)) { throw new ArgumentOutOfRangeException(nameof(expirationDateTime), "The specified expiration date is invalid. Should be greater than today and within 6 months"); } await new SynchronizationContextRemover(); using (var handler = new HttpClientHandler()) { context.Web.EnsureProperty(p => p.Url); using (var httpClient = new PnPHttpProvider(handler)) { string identifierUrl = GetResourceIdentifier(resourceType, webUrl, resourceId); if (string.IsNullOrEmpty(identifierUrl)) { throw new Exception("Identifier of the resource cannot be determined"); } string requestUrl = string.Format("{0}/{1}('{2}')", identifierUrl, SubscriptionsUrlPart, subscriptionId); HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("PATCH"), requestUrl); request.Headers.Add("X-RequestDigest", await context.GetRequestDigestAsync()); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); if (!string.IsNullOrEmpty(accessToken)) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); } WebhookSubscription webhookSubscription; if (string.IsNullOrEmpty(webHookEndPoint)) { webhookSubscription = new WebhookSubscription() { ExpirationDateTime = expirationDateTime }; } else { webhookSubscription = new WebhookSubscription() { NotificationUrl = webHookEndPoint, ExpirationDateTime = expirationDateTime }; } request.Content = new StringContent(JsonConvert.SerializeObject(webhookSubscription), Encoding.UTF8, "application/json"); HttpResponseMessage response = await httpClient.SendAsync(request, new System.Threading.CancellationToken()); if (response.StatusCode != System.Net.HttpStatusCode.NoContent) { // oops...something went wrong, maybe the web hook does not exist? throw new Exception(await response.Content.ReadAsStringAsync()); } else { return(true); } } } }
/// <summary> /// Add a Webhook subscription to a SharePoint resource /// </summary> /// <param name="webUrl">Url of the site holding the list</param> /// <param name="resourceType">The type of Hookable SharePoint resource</param> /// <param name="accessToken">Access token to authenticate against SharePoint</param> /// <param name="context">ClientContext instance to use for authentication</param> /// <param name="subscription">The Webhook subscription to add</param> /// <exception cref="ArgumentOutOfRangeException">Thrown when expiration date is out of valid range.</exception> /// <returns>The added subscription object</returns> public static async Task <WebhookSubscription> AddWebhookSubscriptionAsync(string webUrl, WebHookResourceType resourceType, string accessToken, ClientContext context, WebhookSubscription subscription) { if (!ValidateExpirationDateTime(subscription.ExpirationDateTime)) { throw new ArgumentOutOfRangeException(nameof(subscription.ExpirationDateTime), "The specified expiration date is invalid. Should be greater than today and within 6 months"); } await new SynchronizationContextRemover(); string responseString = null; using (var handler = new HttpClientHandler()) { context.Web.EnsureProperty(p => p.Url); if (string.IsNullOrEmpty(accessToken)) { context.SetAuthenticationCookiesForHandler(handler); } using (var httpClient = new PnPHttpProvider(handler)) { string identifierUrl = GetResourceIdentifier(resourceType, webUrl, subscription.Resource); if (string.IsNullOrEmpty(identifierUrl)) { throw new Exception("Identifier of the resource cannot be determined"); } string requestUrl = identifierUrl + "/" + SubscriptionsUrlPart; using (var request = new HttpRequestMessage(HttpMethod.Post, requestUrl)) { request.Headers.Add("X-RequestDigest", await context.GetRequestDigestAsync()); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); if (!string.IsNullOrEmpty(accessToken)) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); request.Headers.Add("X-RequestDigest", await context.GetRequestDigestAsync().ConfigureAwait(false)); } else { if (context.Credentials is NetworkCredential networkCredential) { handler.Credentials = networkCredential; } request.Headers.Add("X-RequestDigest", await context.GetRequestDigestAsync(handler.CookieContainer).ConfigureAwait(false)); } request.Content = new StringContent(JsonConvert.SerializeObject(subscription), Encoding.UTF8, "application/json"); HttpResponseMessage response = await httpClient.SendAsync(request, new System.Threading.CancellationToken()); if (response.IsSuccessStatusCode) { responseString = await response.Content.ReadAsStringAsync(); } else { // Something went wrong... throw new Exception(await response.Content.ReadAsStringAsync()); } } } } return(JsonConvert.DeserializeObject <WebhookSubscription>(responseString)); }
internal static async Task <string> ExecutePostAsync(this Web web, string endpoint, string payload, string cultureLanguageName = null) { string returnObject = null; var accessToken = web.Context.GetAccessToken(); using (var handler = new HttpClientHandler()) { web.EnsureProperty(w => w.Url); if (string.IsNullOrEmpty(accessToken)) { (web.Context as ClientContext).SetAuthenticationCookiesForHandler(handler); } using (var httpClient = new PnPHttpProvider(handler)) { var requestUrl = $"{web.Url}{endpoint}"; using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUrl)) { request.Headers.Add("accept", "application/json;odata=nometadata"); var requestDigest = string.Empty; if (!string.IsNullOrEmpty(accessToken)) { request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken); requestDigest = await(web.Context as ClientContext).GetRequestDigestAsync().ConfigureAwait(false); } else { if (web.Context.Credentials is NetworkCredential networkCredential) { handler.Credentials = networkCredential; } requestDigest = await(web.Context as ClientContext).GetRequestDigestAsync(handler.CookieContainer).ConfigureAwait(false); } request.Headers.Add("X-RequestDigest", requestDigest); if (!string.IsNullOrWhiteSpace(cultureLanguageName)) { request.Headers.Add("Accept-Language", cultureLanguageName); } if (!string.IsNullOrEmpty(payload)) { ////var jsonBody = JsonConvert.SerializeObject(postObject); var requestBody = new StringContent(payload); MediaTypeHeaderValue sharePointJsonMediaType = MediaTypeHeaderValue.Parse("application/json;odata=nometadata;charset=utf-8"); requestBody.Headers.ContentType = sharePointJsonMediaType; request.Content = requestBody; } // Perform actual post operation HttpResponseMessage response = await httpClient.SendAsync(request, new System.Threading.CancellationToken()); if (response.IsSuccessStatusCode) { // If value empty, URL is taken var responseString = await response.Content.ReadAsStringAsync(); if (responseString != null) { try { returnObject = responseString; } catch { } } } else { // Something went wrong... throw new Exception(await response.Content.ReadAsStringAsync()); } } } } return(await Task.Run(() => returnObject)); }
/// <summary> /// This helper method makes an HTTP request and eventually returns a result /// </summary> /// <param name="httpMethod">The HTTP method for the request</param> /// <param name="requestUrl">The URL of the request</param> /// <param name="responseHeaders">The response headers of the HTTP request (output argument)</param> /// <param name="accessToken">The OAuth 2.0 Access Token for the request, if authorization is required</param> /// <param name="accept">The content type of the accepted response</param> /// <param name="content">The content of the request</param> /// <param name="contentType">The content type of the request</param> /// <param name="referer">The URL Referer for the request</param> /// <param name="resultPredicate">The predicate to retrieve the result, if any</param> /// <param name="requestHeaders">A collection of any custom request headers</param> /// <param name="cookies">Any request cookies values</param> /// <param name="retryCount">Number of times to retry the request</param> /// <param name="delay">Milliseconds to wait before retrying the request. The delay will be increased (doubled) every retry</param> /// <param name="userAgent">UserAgent string value to insert for this request. You can define this value in your app's config file using key="SharePointPnPUserAgent" value="PnPRocks"</param> /// <param name="spContext">An optional SharePoint client context</param> /// <typeparam name="TResult">The type of the result, if any</typeparam> /// <returns>The value of the result, if any</returns> internal static TResult MakeHttpRequest <TResult>( string httpMethod, string requestUrl, out HttpResponseHeaders responseHeaders, string accessToken = null, string accept = null, object content = null, string contentType = null, string referer = null, Func <HttpResponseMessage, TResult> resultPredicate = null, Dictionary <string, string> requestHeaders = null, Dictionary <string, string> cookies = null, int retryCount = 1, int delay = 500, string userAgent = null, ClientContext spContext = null) { HttpClient client = HttpHelper.httpClient; // Define whether to use the default HttpClient object // or a custom one with retry logic and/or with custom request cookies // or a SharePoint client context to rely on if (retryCount >= 1 || (cookies != null && cookies.Count > 0) || spContext != null) { // Let's create a custom HttpHandler var handler = new HttpClientHandler(); // And now create the customized HttpClient object client = new PnPHttpProvider(handler, true, retryCount, delay, userAgent); } // Prepare the variable to hold the result, if any TResult result = default(TResult); responseHeaders = null; Uri requestUri = new Uri(requestUrl); // If we have the token, then handle the HTTP request // Set the Authorization Bearer token if (!string.IsNullOrEmpty(accessToken)) { client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); } if (!string.IsNullOrEmpty(referer)) { client.DefaultRequestHeaders.Referrer = new Uri(referer); } // If there is an accept argument, set the corresponding HTTP header if (!string.IsNullOrEmpty(accept)) { client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add( new MediaTypeWithQualityHeaderValue(accept)); } // Process any additional custom request headers if (requestHeaders != null) { foreach (var requestHeader in requestHeaders) { client.DefaultRequestHeaders.Add(requestHeader.Key, requestHeader.Value); } } // Prepare the content of the request, if any HttpContent requestContent = null; System.IO.Stream streamContent = content as System.IO.Stream; if (streamContent != null) { requestContent = new StreamContent(streamContent); requestContent.Headers.ContentType = new MediaTypeHeaderValue(contentType); } else if (content != null) { var jsonString = content is string ?content.ToString() : JsonConvert.SerializeObject(content, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, ContractResolver = new ODataBindJsonResolver(), }); requestContent = new StringContent(jsonString, Encoding.UTF8, contentType); } // Prepare the HTTP request message with the proper HTTP method HttpRequestMessage request = new HttpRequestMessage( new HttpMethod(httpMethod), requestUrl); // Set the request content, if any if (requestContent != null) { request.Content = requestContent; } // Fire the HTTP request HttpResponseMessage response = client.SendAsync(request).Result; if (response.IsSuccessStatusCode) { // If the response is Success and there is a // predicate to retrieve the result, invoke it if (resultPredicate != null) { result = resultPredicate(response); } // Get any response header and put it in the answer responseHeaders = response.Headers; } else { throw new ApplicationException( string.Format("Exception while invoking endpoint {0}.", requestUrl), #if !NETSTANDARD2_0 new HttpException( (int)response.StatusCode, response.Content.ReadAsStringAsync().Result)); #else new Exception(response.Content.ReadAsStringAsync().Result)); #endif } return(result); }