/// <summary> /// Creates a new Team Site Collection and waits for it to be created /// </summary> /// <param name="clientContext">ClientContext object of a regular site</param> /// <param name="siteCollectionCreationInformation">information about the site to create</param> /// <returns>ClientContext object for the created site collection</returns> public static ClientContext Create(ClientContext clientContext, TeamSiteCollectionCreationInformation siteCollectionCreationInformation) { var context = CreateAsync(clientContext, siteCollectionCreationInformation).GetAwaiter().GetResult(); PollForSiteCreated(context); return(context); }
/// <summary> /// Creates a new Team Site Collection and waits for it to be created /// </summary> /// <param name="clientContext">ClientContext object of a regular site</param> /// <param name="siteCollectionCreationInformation">information about the site to create</param> /// <param name="delayAfterCreation">Defines the number of seconds to wait after creation</param> /// <returns>ClientContext object for the created site collection</returns> public static ClientContext Create(ClientContext clientContext, TeamSiteCollectionCreationInformation siteCollectionCreationInformation, Int32 delayAfterCreation = 0) { var context = CreateAsync(clientContext, siteCollectionCreationInformation, delayAfterCreation).GetAwaiter().GetResult(); return(context); }
/// <summary> /// Creates a new Modern Team Site Collection /// </summary> /// <param name="clientContext">ClientContext object of a regular site</param> /// <param name="siteCollectionCreationInformation">information about the site to create</param> /// <returns>ClientContext object for the created site collection</returns> public static async Task <ClientContext> CreateAsync(ClientContext clientContext, TeamSiteCollectionCreationInformation siteCollectionCreationInformation) { if (siteCollectionCreationInformation.Alias.Contains(" ")) { throw new ArgumentException("Alias cannot contain spaces", "Alias"); } await new SynchronizationContextRemover(); ClientContext responseContext = null; var accessToken = clientContext.GetAccessToken(); if (clientContext.IsAppOnly()) { throw new Exception("App-Only is currently not supported."); } using (var handler = new HttpClientHandler()) { clientContext.Web.EnsureProperty(w => w.Url); // we're not in app-only or user + app context, so let's fall back to cookie based auth if (String.IsNullOrEmpty(accessToken)) { handler.SetAuthenticationCookies(clientContext); } using (var httpClient = new PnPHttpProvider(handler)) { string requestUrl = String.Format("{0}/_api/GroupSiteManager/CreateGroupEx", clientContext.Web.Url); Dictionary <string, object> payload = new Dictionary <string, object>(); payload.Add("displayName", siteCollectionCreationInformation.DisplayName); payload.Add("alias", siteCollectionCreationInformation.Alias); payload.Add("isPublic", siteCollectionCreationInformation.IsPublic); var optionalParams = new Dictionary <string, object>(); optionalParams.Add("Description", siteCollectionCreationInformation.Description != null ? siteCollectionCreationInformation.Description : ""); optionalParams.Add("CreationOptions", new { results = siteCollectionCreationInformation.Lcid != 0 ? new[] { $"SPSiteLanguage:{siteCollectionCreationInformation.Lcid}" } : new object[0], Classification = siteCollectionCreationInformation.Classification != null ? siteCollectionCreationInformation.Classification : "" }); payload.Add("optionalParams", optionalParams); var body = payload; // Serialize request object to JSON var jsonBody = JsonConvert.SerializeObject(body); var requestBody = new StringContent(jsonBody); // Build Http request HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUrl); request.Content = requestBody; request.Headers.Add("accept", "application/json;odata=verbose"); MediaTypeHeaderValue sharePointJsonMediaType = null; MediaTypeHeaderValue.TryParse("application/json;odata=verbose;charset=utf-8", out sharePointJsonMediaType); requestBody.Headers.ContentType = sharePointJsonMediaType; if (!string.IsNullOrEmpty(accessToken)) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); } requestBody.Headers.Add("X-RequestDigest", await clientContext.GetRequestDigest()); // 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(); var responseJson = JObject.Parse(responseString); #if !NETSTANDARD2_0 if (Convert.ToInt32(responseJson["d"]["CreateGroupEx"]["SiteStatus"]) == 2) #else if (responseJson["d"]["CreateGroupEx"]["SiteStatus"].Value <int>() == 2) #endif { responseContext = clientContext.Clone(responseJson["d"]["CreateGroupEx"]["SiteUrl"].ToString()); } else { throw new Exception(responseString); } } else { // Something went wrong... throw new Exception(await response.Content.ReadAsStringAsync()); } } return(await Task.Run(() => responseContext)); } }
/// <summary> /// Creates a new Modern Team Site Collection /// </summary> /// <param name="clientContext">ClientContext object of a regular site</param> /// <param name="siteCollectionCreationInformation">information about the site to create</param> /// <param name="delayAfterCreation">Defines the number of seconds to wait after creation</param> /// <param name="maxRetryCount">Maximum number of retries for a pending site provisioning. Default 12 retries.</param> /// <param name="retryDelay">Delay between retries for a pending site provisioning. Default 10 seconds.</param> /// <returns>ClientContext object for the created site collection</returns> public static async Task <ClientContext> CreateAsync(ClientContext clientContext, TeamSiteCollectionCreationInformation siteCollectionCreationInformation, Int32 delayAfterCreation = 0, Int32 maxRetryCount = 12, // Maximum number of retries (12 x 10 sec = 120 sec = 2 mins) Int32 retryDelay = 1000 * 10 // Wait time default to 10sec ) { if (siteCollectionCreationInformation.Alias.Contains(" ")) { throw new ArgumentException("Alias cannot contain spaces", "Alias"); } await new SynchronizationContextRemover(); ClientContext responseContext = null; if (clientContext.IsAppOnly()) { throw new Exception("App-Only is currently not supported."); } var accessToken = clientContext.GetAccessToken(); using (var handler = new HttpClientHandler()) { clientContext.Web.EnsureProperty(w => w.Url); // we're not in app-only or user + app context, so let's fall back to cookie based auth if (String.IsNullOrEmpty(accessToken)) { handler.SetAuthenticationCookies(clientContext); } using (var httpClient = new PnPHttpProvider(handler)) { string requestUrl = String.Format("{0}/_api/GroupSiteManager/CreateGroupEx", clientContext.Web.Url); Dictionary <string, object> payload = new Dictionary <string, object>(); payload.Add("displayName", siteCollectionCreationInformation.DisplayName); payload.Add("alias", siteCollectionCreationInformation.Alias); payload.Add("isPublic", siteCollectionCreationInformation.IsPublic); var optionalParams = new Dictionary <string, object>(); optionalParams.Add("Description", siteCollectionCreationInformation.Description ?? ""); optionalParams.Add("Classification", siteCollectionCreationInformation.Classification ?? ""); var creationOptionsValues = new List <string>(); if (siteCollectionCreationInformation.Lcid != 0) { creationOptionsValues.Add($"SPSiteLanguage:{siteCollectionCreationInformation.Lcid}"); } creationOptionsValues.Add($"HubSiteId:{siteCollectionCreationInformation.HubSiteId}"); optionalParams.Add("CreationOptions", creationOptionsValues); if (siteCollectionCreationInformation.Owners != null && siteCollectionCreationInformation.Owners.Length > 0) { optionalParams.Add("Owners", siteCollectionCreationInformation.Owners); } payload.Add("optionalParams", optionalParams); var body = payload; // Serialize request object to JSON var jsonBody = JsonConvert.SerializeObject(body); var requestBody = new StringContent(jsonBody); // Build Http request HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUrl); request.Content = requestBody; request.Headers.Add("accept", "application/json;odata.metadata=none"); request.Headers.Add("odata-version", "4.0"); MediaTypeHeaderValue sharePointJsonMediaType = null; MediaTypeHeaderValue.TryParse("application/json;odata.metadata=none;charset=utf-8", out sharePointJsonMediaType); requestBody.Headers.ContentType = sharePointJsonMediaType; if (!string.IsNullOrEmpty(accessToken)) { request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); } requestBody.Headers.Add("X-RequestDigest", await clientContext.GetRequestDigest()); // 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(); var responseJson = JObject.Parse(responseString); #if !NETSTANDARD2_0 if (Convert.ToInt32(responseJson["SiteStatus"]) == 2) #else if (responseJson["SiteStatus"].Value <int>() == 2) #endif { responseContext = clientContext.Clone(responseJson["SiteUrl"].ToString()); } else { /* * BEGIN : Changes to address the SiteStatus=Provisioning scenario */ if (Convert.ToInt32(responseJson["SiteStatus"]) == 1 && string.IsNullOrWhiteSpace(Convert.ToString(responseJson["ErrorMessage"]))) { var spOperationsMaxRetryCount = maxRetryCount; var spOperationsRetryWait = retryDelay; var siteCreated = false; var siteUrl = string.Empty; var retryAttempt = 1; do { if (retryAttempt > 1) { System.Threading.Thread.Sleep(retryAttempt * spOperationsRetryWait); } try { var groupId = responseJson["GroupId"].ToString(); var siteStatusRequestUrl = $"{clientContext.Web.Url}/_api/groupsitemanager/GetSiteStatus('{groupId}')"; var siteStatusRequest = new HttpRequestMessage(HttpMethod.Get, siteStatusRequestUrl); siteStatusRequest.Headers.Add("accept", "application/json;odata=verbose"); if (!string.IsNullOrEmpty(accessToken)) { siteStatusRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); } siteStatusRequest.Headers.Add("X-RequestDigest", await clientContext.GetRequestDigest()); var siteStatusResponse = await httpClient.SendAsync(siteStatusRequest, new System.Threading.CancellationToken()); var siteStatusResponseString = await siteStatusResponse.Content.ReadAsStringAsync(); var siteStatusResponseJson = JObject.Parse(siteStatusResponseString); if (siteStatusResponse.IsSuccessStatusCode) { var siteStatus = Convert.ToInt32(siteStatusResponseJson["d"]["GetSiteStatus"]["SiteStatus"].ToString()); if (siteStatus == 2) { siteCreated = true; siteUrl = siteStatusResponseJson["d"]["GetSiteStatus"]["SiteUrl"].ToString(); } } } catch (Exception) { // Just skip it and retry after a delay } retryAttempt++; }while (!siteCreated && retryAttempt <= spOperationsMaxRetryCount); if (siteCreated) { responseContext = clientContext.Clone(siteUrl); } else { throw new Exception("OfficeDevPnP.Core.Sites.SiteCollection.CreateAsync: Could not create team site."); } } else { throw new Exception(responseString); } /* * END : Changes to address the SiteStatus=Provisioning scenario */ } // If there is a delay, let's wait if (delayAfterCreation > 0) { System.Threading.Thread.Sleep(TimeSpan.FromSeconds(delayAfterCreation)); } } else { // Something went wrong... throw new Exception(await response.Content.ReadAsStringAsync()); } } return(await Task.Run(() => responseContext)); } }