/// <summary> /// Get all webhook subscriptions on a given SharePoint resource /// </summary> /// <param name="webUrl">Url of the site holding the resource</param> /// <param name="resourceType">The type of SharePoint resource</param> /// <param name="resourceId">The Unique Identifier of the resource</param> /// <param name="accessToken">Access token to authenticate against SharePoint</param> /// <param name="context">ClientContext instance to use for authentication</param> /// <returns>Collection of <see cref="WebhookSubscription"/> instances, one per returned web hook</returns> public static async Task <ResponseModel <WebhookSubscription> > GetWebhooksSubscriptionsAsync(string webUrl, WebHookResourceType resourceType, string resourceId, string accessToken, ClientContext context) { 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, resourceId); if (string.IsNullOrEmpty(identifierUrl)) { throw new Exception("Identifier of the resource cannot be determined"); } string requestUrl = identifierUrl + "/" + SubscriptionsUrlPart; using (var request = new HttpRequestMessage(HttpMethod.Get, requestUrl)) { 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)); } HttpResponseMessage response = await httpClient.SendAsync(request, new System.Threading.CancellationToken()); if (response.IsSuccessStatusCode) { responseString = await response.Content.ReadAsStringAsync(); } else { // oops...something went wrong throw new Exception(await response.Content.ReadAsStringAsync()); } } } } return(JsonConvert.DeserializeObject <ResponseModel <WebhookSubscription> >(responseString)); }
/// <summary> /// Deletes 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="accessToken">Access token to authenticate against SharePoint</param> /// <param name="context">ClientContext instance to use for authentication</param> /// <returns>true if succesful, exception in case something went wrong</returns> public static async Task <bool> RemoveWebhookSubscriptionAsync(string webUrl, WebHookResourceType resourceType, string resourceId, string subscriptionId, string accessToken, ClientContext context) { await new SynchronizationContextRemover(); 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, 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); using (var request = new HttpRequestMessage(HttpMethod.Delete, 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)); } 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> /// Executes a REST Get request. /// </summary> /// <param name="web">The current web to execute the request against</param> /// <param name="endpoint">The full endpoint url, exluding the URL of the web, e.g. /_api/web/lists</param> /// <returns></returns> internal static async Task <string> ExecuteGetAsync(this Web web, string endpoint) { string returnObject = null; var accessToken = web.Context.GetAccessToken(); using (var handler = new HttpClientHandler()) { web.EnsureProperty(w => w.Url); using (var httpClient = new PnPHttpProvider(handler)) { var requestUrl = $"{web.Url}{endpoint}"; HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUrl); request.Headers.Add("accept", "application/json;odata=nometadata"); if (!string.IsNullOrEmpty(accessToken)) { request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken); } else { if (web.Context.Credentials is NetworkCredential networkCredential) { handler.Credentials = networkCredential; } } var requestDigest = await(web.Context as ClientContext).GetRequestDigestAsync().ConfigureAwait(false); request.Headers.Add("X-RequestDigest", requestDigest); // 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> /// 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); 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; HttpRequestMessage 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.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)); }
/// <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); } } } }
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)); }