diff --git a/Core/OfficeDevPnP.Core.Tests/App.config.sample b/Core/OfficeDevPnP.Core.Tests/App.config.sample
index 2c7db283f3..cf997c35f6 100644
--- a/Core/OfficeDevPnP.Core.Tests/App.config.sample
+++ b/Core/OfficeDevPnP.Core.Tests/App.config.sample
@@ -61,7 +61,7 @@
-
+
@@ -76,6 +76,9 @@
+
+
+
diff --git a/Core/OfficeDevPnP.Core.Tests/Extensions/ListExtensionsTests.cs b/Core/OfficeDevPnP.Core.Tests/Extensions/ListExtensionsTests.cs
index 327a2e0798..47ab519d00 100644
--- a/Core/OfficeDevPnP.Core.Tests/Extensions/ListExtensionsTests.cs
+++ b/Core/OfficeDevPnP.Core.Tests/Extensions/ListExtensionsTests.cs
@@ -62,7 +62,7 @@ public void Initialize()
// List
- _textFieldId = Guid.NewGuid();
+ _textFieldId = Guid.NewGuid();
var fieldCI = new FieldCreationInformation(FieldType.Text)
{
@@ -240,7 +240,7 @@ public void ListExistsByUrlPathParamTest()
false);
Assert.IsNotNull(list);
- Assert.IsTrue(clientContext.Web.ListExists(new Uri(siteRelativePath,UriKind.Relative)));
+ Assert.IsTrue(clientContext.Web.ListExists(new Uri(siteRelativePath, UriKind.Relative)));
//Delete List
list.DeleteObject();
@@ -306,5 +306,104 @@ public void SetDefaultColumnValuesTest()
}
#endregion
+ #region Webhooks tests
+ [TestMethod]
+ public void SubscribeWebhookTest()
+ {
+ using (var clientContext = TestCommon.CreateClientContext())
+ {
+ var testList = clientContext.Web.Lists.GetById(_listId);
+ clientContext.Load(testList);
+ clientContext.ExecuteQueryRetry();
+
+ WebhookSubscription expectedSubscription = new WebhookSubscription()
+ {
+ ExpirationDateTime = DateTime.Today.AddMonths(3),
+ NotificationUrl = TestCommon.TestWebhookUrl,
+ Resource = TestCommon.DevSiteUrl + string.Format("/_api/lists('{0}')", _listId)
+ };
+ WebhookSubscription actualSubscription = testList.AddWebhookSubscription(TestCommon.TestWebhookUrl, 3);
+
+ // Compare properties of expected and actual
+ Assert.IsTrue(Equals(expectedSubscription.ClientState, actualSubscription.ClientState)
+ && Equals(expectedSubscription.ExpirationDateTime, actualSubscription.ExpirationDateTime)
+ && Equals(expectedSubscription.NotificationUrl, actualSubscription.NotificationUrl)
+ && Equals(expectedSubscription.Resource, actualSubscription.Resource));
+ }
+ }
+
+ [TestMethod]
+ public void UnsubscribeWebhookTestFromGuid()
+ {
+ using (var clientContext = TestCommon.CreateClientContext())
+ {
+ var testList = clientContext.Web.Lists.GetById(_listId);
+ clientContext.Load(testList);
+ clientContext.ExecuteQueryRetry();
+
+
+ WebhookSubscription actualSubscription = testList.AddWebhookSubscription(TestCommon.TestWebhookUrl, 3);
+
+ bool result = testList.RemoveWebhookSubscription(Guid.Parse(actualSubscription.Id));
+
+ Assert.IsTrue(result);
+ }
+ }
+
+ [TestMethod]
+ public void UnsubscribeWebhookTestFromEntity()
+ {
+ using (var clientContext = TestCommon.CreateClientContext())
+ {
+ var testList = clientContext.Web.Lists.GetById(_listId);
+ clientContext.Load(testList);
+ clientContext.ExecuteQueryRetry();
+
+
+ WebhookSubscription actualSubscription = testList.AddWebhookSubscription(TestCommon.TestWebhookUrl, 3);
+
+ bool result = testList.RemoveWebhookSubscription(actualSubscription);
+
+ Assert.IsTrue(result);
+ }
+ }
+
+ [TestMethod]
+ public void UnsubscribeWebhookTestFromString()
+ {
+ using (var clientContext = TestCommon.CreateClientContext())
+ {
+ var testList = clientContext.Web.Lists.GetById(_listId);
+ clientContext.Load(testList);
+ clientContext.ExecuteQueryRetry();
+
+
+ WebhookSubscription actualSubscription = testList.AddWebhookSubscription(TestCommon.TestWebhookUrl, 3);
+
+ bool result = testList.RemoveWebhookSubscription(actualSubscription.Id);
+
+ Assert.IsTrue(result);
+ }
+ }
+
+ [TestMethod]
+ public void GetAllWebhookSubscriptionsTest()
+ {
+ using (var clientContext = TestCommon.CreateClientContext())
+ {
+ var testList = clientContext.Web.Lists.GetById(_listId);
+ clientContext.Load(testList);
+ clientContext.ExecuteQueryRetry();
+
+
+ WebhookSubscription createdSubscription = testList.AddWebhookSubscription(TestCommon.TestWebhookUrl, 3);
+
+ IList actualSubscriptions = testList.GetAllWebhookSubscriptions();
+
+ Assert.IsTrue(actualSubscriptions.Any(s => s == createdSubscription));
+ }
+ }
+ #endregion
+
}
}
diff --git a/Core/OfficeDevPnP.Core.Tests/TestCommon.cs b/Core/OfficeDevPnP.Core.Tests/TestCommon.cs
index 05a750150c..af43f8f643 100644
--- a/Core/OfficeDevPnP.Core.Tests/TestCommon.cs
+++ b/Core/OfficeDevPnP.Core.Tests/TestCommon.cs
@@ -18,6 +18,7 @@ static TestCommon()
// Read configuration data
TenantUrl = ConfigurationManager.AppSettings["SPOTenantUrl"];
DevSiteUrl = ConfigurationManager.AppSettings["SPODevSiteUrl"];
+ TestWebhookUrl = ConfigurationManager.AppSettings["TestWebhookUrl"];
#if !ONPREMISES
if (string.IsNullOrEmpty(TenantUrl))
@@ -30,6 +31,8 @@ static TestCommon()
throw new ConfigurationErrorsException("Dev site url in App.config are not set up.");
}
+
+
// Trim trailing slashes
TenantUrl = TenantUrl.TrimEnd(new[] { '/' });
DevSiteUrl = DevSiteUrl.TrimEnd(new[] { '/' });
@@ -146,6 +149,8 @@ static TestCommon()
///
public static string HighTrustCertificateStoreThumbprint { get; set; }
+ public static string TestWebhookUrl { get; set; }
+
public static String AzureStorageKey
{
get
@@ -188,9 +193,9 @@ public static String ScriptSite
return ConfigurationManager.AppSettings["ScriptSite"];
}
}
-#endregion
+ #endregion
-#region Methods
+ #region Methods
public static ClientContext CreateClientContext()
{
return CreateContext(DevSiteUrl, Credentials);
@@ -291,7 +296,7 @@ private static ClientContext CreateContext(string contextUrl, ICredentials crede
if (new Uri(DevSiteUrl).DnsSafeHost.Contains("spoppe.com"))
{
- context = am.GetAppOnlyAuthenticatedContext(contextUrl, Core.Utilities.TokenHelper.GetRealmFromTargetUrl(new Uri(DevSiteUrl)), AppId, AppSecret, acsHostUrl: "windows-ppe.net", globalEndPointPrefix:"login");
+ context = am.GetAppOnlyAuthenticatedContext(contextUrl, Core.Utilities.TokenHelper.GetRealmFromTargetUrl(new Uri(DevSiteUrl)), AppId, AppSecret, acsHostUrl: "windows-ppe.net", globalEndPointPrefix: "login");
}
else
{
@@ -319,6 +324,6 @@ private static SecureString GetSecureString(string input)
return secureString;
}
-#endregion
+ #endregion
}
}
diff --git a/Core/OfficeDevPnP.Core/Entities/WebhookSubscription.cs b/Core/OfficeDevPnP.Core/Entities/WebhookSubscription.cs
new file mode 100644
index 0000000000..7537f2e05c
--- /dev/null
+++ b/Core/OfficeDevPnP.Core/Entities/WebhookSubscription.cs
@@ -0,0 +1,31 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OfficeDevPnP.Core.Entities
+{
+ ///
+ /// Represents the payload of a Http message
+ ///
+ public class WebhookSubscription
+ {
+ [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+ public string Id { get; set; }
+
+ [JsonProperty(PropertyName = "clientState", NullValueHandling = NullValueHandling.Ignore)]
+ public string ClientState { get; set; }
+
+ [JsonProperty(PropertyName = "expirationDateTime")]
+ public DateTime ExpirationDateTime { get; set; }
+
+ [JsonProperty(PropertyName = "notificationUrl")]
+ public string NotificationUrl { get; set; }
+
+ [JsonProperty(PropertyName = "resource", NullValueHandling = NullValueHandling.Ignore)]
+ public string Resource { get; set; }
+
+ }
+}
diff --git a/Core/OfficeDevPnP.Core/Extensions/ListExtensions.cs b/Core/OfficeDevPnP.Core/Extensions/ListExtensions.cs
index 146a82389c..8b685566c2 100644
--- a/Core/OfficeDevPnP.Core/Extensions/ListExtensions.cs
+++ b/Core/OfficeDevPnP.Core/Extensions/ListExtensions.cs
@@ -14,6 +14,8 @@
using OfficeDevPnP.Core.Diagnostics;
using OfficeDevPnP.Core.Utilities;
using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using OfficeDevPnP.Core.Utilities.Webhooks;
namespace Microsoft.SharePoint.Client
{
@@ -138,6 +140,115 @@ in list.EventReceivers
#endregion
+ #region Webhooks
+ ///
+ /// Add the a Webhook subscription to a list
+ /// Note: If the access token is not specified, it will cost a dummy request to retrieve it
+ ///
+ /// The list to add a Webhook subscription to
+ /// The Webhook endpoint URL
+ /// The expiration date of the subscription
+ /// The client state to use in the Webhook subscription
+ /// (optional) The access token to SharePoint
+ /// The added subscription object
+ public static WebhookSubscription AddWebhookSubscription(this List list, string notificationUrl,
+ DateTime expirationDate, string clientState = null, string accessToken = null)
+ {
+ // Get the access from the client context if not specified.
+ accessToken = accessToken ?? Utility.GetAccessTokenFromClientContext(list.Context);
+
+ return WebhookUtility.AddWebhookSubscriptionAsync(list.Context.Url,
+ EHookableResourceType.List, accessToken, new WebhookSubscription()
+ {
+ Resource = list.Id.ToString(),
+ ExpirationDateTime = expirationDate,
+ NotificationUrl = notificationUrl,
+ ClientState = clientState
+ }).Result;
+ }
+
+ ///
+ /// Add the a Webhook subscription to a list
+ /// Note: If the access token is not specified, it will cost a dummy request to retrieve it
+ ///
+ /// The list to add a Webhook subscription to
+ /// The Webhook endpoint URL
+ /// The validity of the subscriptions in months
+ /// The client state to use in the Webhook subscription
+ /// (optional) The access token to SharePoint
+ /// The added subscription object
+ public static WebhookSubscription AddWebhookSubscription(this List list, string notificationUrl,
+ int validityInMonths = 3, string clientState = null, string accessToken = null)
+ {
+ // Get the access from the client context if not specified.
+ accessToken = accessToken ?? Utility.GetAccessTokenFromClientContext(list.Context);
+
+ return WebhookUtility.AddWebhookSubscriptionAsync(list.Context.Url,
+ EHookableResourceType.List, accessToken, list.Id.ToString(),
+ notificationUrl, clientState, validityInMonths).Result;
+ }
+
+ ///
+ /// Remove a Webhook subscription from the list
+ /// Note: If the access token is not specified, it will cost a dummy request to retrieve it
+ ///
+ /// The list to remove the Webhook subscription from
+ /// The id of the subscription to remove
+ /// (optional) The access token to SharePoint
+ /// true if the removal succeeded, false otherwise
+ public static bool RemoveWebhookSubscription(this List list, string subscriptionId, string accessToken = null)
+ {
+ // Get the access from the client context if not specified.
+ accessToken = accessToken ?? Utility.GetAccessTokenFromClientContext(list.Context);
+
+ return WebhookUtility.DeleteWebhookSubscriptionAsync(list.Context.Url, EHookableResourceType.List, list.Id.ToString(),
+ subscriptionId, accessToken).Result;
+ }
+
+ ///
+ /// Remove a Webhook subscription from the list
+ /// Note: If the access token is not specified, it will cost a dummy request to retrieve it
+ ///
+ /// The list to remove the Webhook subscription from
+ /// The id of the subscription to remove
+ /// (optional) The access token to SharePoint
+ /// true if the removal succeeded, false otherwise
+ public static bool RemoveWebhookSubscription(this List list, Guid subscriptionId, string accessToken = null)
+ {
+ return RemoveWebhookSubscription(list, subscriptionId.ToString(), accessToken);
+ }
+
+ ///
+ /// Remove a Webhook subscription from the list
+ /// Note: If the access token is not specified, it will cost a dummy request to retrieve it
+ ///
+ /// The list to remove the Webhook subscription from
+ /// The subscription to remove
+ /// (optional) The access token to SharePoint
+ /// true if the removal succeeded, false otherwise
+ public static bool RemoveWebhookSubscription(this List list, WebhookSubscription subscription, string accessToken = null)
+ {
+ return RemoveWebhookSubscription(list, subscription.Id, accessToken);
+ }
+
+ ///
+ /// Get all the existing Webhooks subscriptions of the list
+ /// Note: If the access token is not specified, it will cost a dummy request to retrieve it
+ ///
+ /// The list to get the subscriptions of
+ /// (optional) The access token to SharePoint
+ /// The collection of Webhooks subscriptions of the list
+ public static IList GetAllWebhookSubscriptions(this List list, string accessToken = null)
+ {
+ // Get the access from the client context if not specified.
+ accessToken = accessToken ?? Utility.GetAccessTokenFromClientContext(list.Context);
+
+ return WebhookUtility.GetWebhooksSubscriptionsAsync(list.Context.Url,
+ EHookableResourceType.List, list.Id.ToString(), accessToken).Result.Value;
+ }
+
+ #endregion
+
#region List Properties
///
@@ -615,7 +726,7 @@ private static void SetJSLinkCustomizationsImplementation(List list, File file,
var wp = wpd.WebPart;
if (wp.Properties.FieldValues.Keys.Contains("JSLink"))
- {
+ {
wp.Properties["JSLink"] = jslink;
wpd.SaveWebPartChanges();
@@ -903,7 +1014,7 @@ public static void SetListPermission(this List list, Principal principal, RoleTy
// Get role type
var roleDefinition = web.RoleDefinitions.GetByType(roleType);
- var rdbColl = new RoleDefinitionBindingCollection(web.Context) {roleDefinition};
+ var rdbColl = new RoleDefinitionBindingCollection(web.Context) { roleDefinition };
// Set custom permission to the list
list.RoleAssignments.Add(principal, rdbColl);
diff --git a/Core/OfficeDevPnP.Core/OfficeDevPnP.Core.csproj b/Core/OfficeDevPnP.Core/OfficeDevPnP.Core.csproj
index 40412af2da..a31fb4f555 100644
--- a/Core/OfficeDevPnP.Core/OfficeDevPnP.Core.csproj
+++ b/Core/OfficeDevPnP.Core/OfficeDevPnP.Core.csproj
@@ -378,6 +378,7 @@
+
@@ -830,6 +831,8 @@
+
+
diff --git a/Core/OfficeDevPnP.Core/Utilities/Utility.cs b/Core/OfficeDevPnP.Core/Utilities/Utility.cs
index 6e22b4007d..a4448e4cf5 100644
--- a/Core/OfficeDevPnP.Core/Utilities/Utility.cs
+++ b/Core/OfficeDevPnP.Core/Utilities/Utility.cs
@@ -7,8 +7,19 @@ namespace OfficeDevPnP.Core.Utilities
{
public static partial class Utility
{
-
-
+
+ public static string GetAccessTokenFromClientContext(ClientRuntimeContext clientContext)
+ {
+ string accessToken = null;
+ // Issue a dummy request to get it from the Authorization header
+ clientContext.ExecutingWebRequest += (s, e) =>
+ {
+ string authorization = e.WebRequestExecutor.RequestHeaders["Authorization"];
+ accessToken = authorization.Replace("Bearer ", string.Empty);
+ };
+ clientContext.ExecuteQueryRetry();
+ return accessToken;
+ }
///
/// Returns the healthscore for a SharePoint Server
diff --git a/Core/OfficeDevPnP.Core/Utilities/Webhooks/ResponseModel.cs b/Core/OfficeDevPnP.Core/Utilities/Webhooks/ResponseModel.cs
new file mode 100644
index 0000000000..56eb85d503
--- /dev/null
+++ b/Core/OfficeDevPnP.Core/Utilities/Webhooks/ResponseModel.cs
@@ -0,0 +1,20 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OfficeDevPnP.Core.Utilities.Webhooks
+{
+
+ ///
+ ///
+ ///
+ internal class ResponseModel
+ {
+
+ [JsonProperty(PropertyName = "value")]
+ public List Value { get; set; }
+ }
+}
diff --git a/Core/OfficeDevPnP.Core/Utilities/Webhooks/WebhookUtility.cs b/Core/OfficeDevPnP.Core/Utilities/Webhooks/WebhookUtility.cs
new file mode 100644
index 0000000000..c5a173fb29
--- /dev/null
+++ b/Core/OfficeDevPnP.Core/Utilities/Webhooks/WebhookUtility.cs
@@ -0,0 +1,210 @@
+using Newtonsoft.Json;
+using OfficeDevPnP.Core.Entities;
+using OfficeDevPnP.Core.Utilities.Webhooks;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OfficeDevPnP.Core.Utilities
+{
+ ///
+ /// The list of Hookable Resource T^ypes
+ ///
+ public enum EHookableResourceType
+ {
+ List,
+ // TODO Implement with upcoming support of other types
+ //Site,
+ //...
+ }
+
+ ///
+ /// Class containing utility methods to manage Webhook on a SharePoint resource
+ /// Adapted from https://github.com/SharePoint/sp-dev-samples/blob/master/Samples/WebHooks.List/SharePoint.WebHooks.Common/WebHookManager.cs
+ ///
+ internal class WebhookUtility
+ {
+
+ private const string SubscriptionsUrlPart = "subscriptions";
+ private const string ListIdentifierFormat = @"{0}/_api/web/lists('{1}')";
+ // TODO Implement with upcoming support of other types
+ //private const string WebIdentifierFormat = @"{0}/_api/web('{1}')";
+
+ ///
+ /// Add a Webhook subscription to a SharePoint resource
+ ///
+ /// Url of the site holding the list
+ /// The type of Hookable SharePoint resource
+ /// Access token to authenticate against SharePoint
+ /// The Webhook subscription to add
+ /// The added subscription object
+ public static async Task AddWebhookSubscriptionAsync(string webUrl,
+ EHookableResourceType resourceType,
+ string accessToken, WebhookSubscription subscription)
+ {
+ string responseString = null;
+ using (var httpClient = new HttpClient())
+ {
+ 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.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
+
+ request.Content = new StringContent(JsonConvert.SerializeObject(subscription),
+ Encoding.UTF8, "application/json");
+
+ HttpResponseMessage response = await httpClient.SendAsync(request);
+
+ if (response.IsSuccessStatusCode)
+ {
+ responseString = await response.Content.ReadAsStringAsync();
+ }
+ else
+ {
+ // Something went wrong...
+ throw new Exception(await response.Content.ReadAsStringAsync());
+ }
+ }
+
+ return JsonConvert.DeserializeObject(responseString);
+ }
+
+ ///
+ /// Add a Webhook subscription to a SharePoint resource
+ ///
+ /// Url of the site holding the list
+ /// The type of Hookable SharePoint resource
+ /// Access token to authenticate against SharePoint
+ /// The Unique Identifier of the resource
+ /// The Webhook endpoint URL
+ /// The client state to use in the Webhook subscription
+ /// The validity of the subscriptions in months
+ /// The added subscription object
+ public static async Task AddWebhookSubscriptionAsync(string webUrl,
+ EHookableResourceType resourceType, string accessToken,
+ string resourceId, string notificationUrl, string clientState = null, int validityInMonths = 3)
+ {
+ var subscription = new WebhookSubscription()
+ {
+ Resource = resourceId,
+ NotificationUrl = notificationUrl,
+ ExpirationDateTime = DateTime.Now.AddMonths(validityInMonths).ToUniversalTime(),
+ ClientState = clientState
+ };
+
+ return await AddWebhookSubscriptionAsync(webUrl, resourceType, accessToken, subscription);
+ }
+
+
+ ///
+ /// Deletes an existing SharePoint list web hook
+ ///
+ /// Url of the site holding the list
+ /// The type of Hookable SharePoint resource
+ /// Id of the list
+ /// Id of the web hook subscription that we need to delete
+ /// Access token to authenticate against SharePoint
+ /// true if succesful, exception in case something went wrong
+ public static async Task DeleteWebhookSubscriptionAsync(string webUrl, EHookableResourceType resourceType,
+ string resourceId, string subscriptionId, string accessToken)
+ {
+ using (var httpClient = new HttpClient())
+ {
+ 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(HttpMethod.Delete, requestUrl);
+ request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
+
+ HttpResponseMessage response = await httpClient.SendAsync(request);
+
+ 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;
+ }
+ }
+ }
+
+ ///
+ /// Get all webhook subscriptions on a given SharePoint resource
+ ///
+ /// Url of the site holding the list
+ /// The type of Hookable SharePoint resource
+ /// The Unique Identifier of the resource
+ /// Access token to authenticate against SharePoint
+ /// Collection of instances, one per returned web hook
+ public static async Task> GetWebhooksSubscriptionsAsync(string webUrl, EHookableResourceType resourceType, string resourceId, string accessToken)
+ {
+ string responseString = null;
+ using (var httpClient = new HttpClient())
+ {
+ string identifierUrl = GetResourceIdentifier(resourceType, webUrl, resourceId);
+ if (string.IsNullOrEmpty(identifierUrl))
+ throw new Exception("Identifier of the resource cannot be determined");
+
+ string requestUrl = identifierUrl + "/" + SubscriptionsUrlPart;
+
+ HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUrl);
+ request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
+
+ HttpResponseMessage response = await httpClient.SendAsync(request);
+
+ if (response.IsSuccessStatusCode)
+ {
+ responseString = await response.Content.ReadAsStringAsync();
+ }
+ else
+ {
+ // oops...something went wrong
+ throw new Exception(await response.Content.ReadAsStringAsync());
+ }
+ }
+
+ return JsonConvert.DeserializeObject>(responseString);
+ }
+
+ ///
+ /// Get the proper identifier Url according to the resource type
+ /// (No great utility currently with the support for lists only,
+ /// but will be later with the support for other resources)
+ ///
+ /// The type of resource
+ /// The URL of the SharePoint web
+ /// The id part of the resource
+ /// The well forned resource identifier URL
+ private static string GetResourceIdentifier(EHookableResourceType resourceType, string webUrl, string id)
+ {
+ switch (resourceType)
+ {
+ case EHookableResourceType.List:
+ return string.Format(ListIdentifierFormat, webUrl, id);
+ //case EHookableResourceType.Site:
+ default:
+ return null;
+ }
+ }
+ }
+
+
+
+
+}