7

I have been trying out to create site collection using CSOM but unable to fins and class which creates site collection.

I have read in MSDN that CSOM runs as site collection scope hence creating site collection permission is not available.

Sub-Site i am able to create properly but unable to create site collection.

4 Answers 4

5

Tenant.CreateSite method queues a site collection for creation with the specified properties. Tenant class is a part of Microsoft.Online.SharePoint.Client.Tenant.dll (SharePoint Online Management Shell)

How to create site collection via CSOM in SharePoint 2013

using System;
using System.Security;
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.SharePoint.Client;

namespace CSOMProvisioning
{
    class Program
    {
        static void Main(string[] args)
        {

            const string username = "[email protected]";
            const string password = "password";
            const string tenantAdminUrl = "https://contoso-admin.sharepoint.com/";
            var securedPassword = new SecureString();
            foreach (var c in password.ToCharArray()) securedPassword.AppendChar(c);
            var credentials = new SharePointOnlineCredentials(username, securedPassword);



            using (var context = new ClientContext(tenantAdminUrl))
            {
                context.Credentials = credentials;
                CreateSite(context, "https://contoso.sharepoint.com/sites/marketing","Marketing");
            }

        }


        /// <summary>
        /// Create a new site.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="url">rootsite + "/" + managedPath + "/" + sitename: e.g. "https://auto.contoso.com/sites/site1"</param>
        /// <param name="title">site title: e.g. "Test Site"</param>
        /// <param name="owner">site owner: e.g. [email protected]</param>
        /// <param name="template">The site template used to create this new site</param>
        /// <param name="localeId"></param>
        /// <param name="compatibilityLevel"></param>
        /// <param name="storageQuota"></param>
        /// <param name="resourceQuota"></param>
        /// <param name="timeZoneId"></param>
        internal static void CreateSite(ClientContext context, String url, String owner, String title =null, String template = null, uint? localeId = null, int? compatibilityLevel = null, long? storageQuota = null, double? resourceQuota = null, int? timeZoneId = null)
        {
            var tenant = new Tenant(context);

            if (url == null)
                throw new ArgumentException("Site Url must be specified");

            if (string.IsNullOrEmpty(owner))
                throw new ArgumentException("Site Owner must be specified");

            var siteCreationProperties = new SiteCreationProperties {Url = url, Owner = owner};
            if (!string.IsNullOrEmpty(template))
                siteCreationProperties.Template = template;
            if (!string.IsNullOrEmpty(title))
                siteCreationProperties.Title = title;
            if (localeId.HasValue)
                siteCreationProperties.Lcid = localeId.Value;
            if (compatibilityLevel.HasValue)
                siteCreationProperties.CompatibilityLevel = compatibilityLevel.Value;
            if (storageQuota.HasValue)
                siteCreationProperties.StorageMaximumLevel = storageQuota.Value;
            if (resourceQuota.HasValue)
                siteCreationProperties.UserCodeMaximumLevel = resourceQuota.Value;
            if (timeZoneId.HasValue)
                siteCreationProperties.TimeZoneId = timeZoneId.Value;
            var siteOp = tenant.CreateSite(siteCreationProperties);
            context.Load(siteOp);
            context.ExecuteQuery();

        }



    }
}
1
  • 1
    Will this code work in On-Prem 2013?
    – Asad Refai
    Commented Jan 3, 2018 at 10:35
3

This example is taken from a SharePoint Online environment with provided hosted apps in mind. Creating a console application, adding reference to

  • Microsoft.SharePoint.Client.dll
  • Microsoft.SharePoint.Client.Runtime.dll
  • Microsoft.Online.SharePoint.Client.Tenant.dll

and pasting this snippet to the main method should do the trick.

var SHAREPOINT_PID = "00000003-0000-0ff1-ce00-000000000000"; // SharePoint constant
var tenantAdminUri = new Uri("https://<TENANT>-admin.sharepoint.com");
var token = TokenHelper.GetAppOnlyAccessToken(SHAREPOINT_PID, tenantAdminUri.Authority, null).AccessToken;

using (var context = TokenHelper.GetClientContextWithAccessToken(tenantAdminUri.ToString(), token))
{
    var tenant = new Tenant(context);
    var properties = new SiteCreationProperties()
    {
        Url = "https://<TENANT>.sharepoint.com/sites/site1",
        Owner = "<USER>@<TENANT>.onmicrosoft.com",
        Template = "STS#0",
        StorageMaximumLevel = 1000,
        UserCodeMaximumLevel = 300
    };
    tenant.CreateSite(properties);

    context.Load(tenant);
    context.ExecuteQuery();
}

In this example I’ve created a simple console application but it might as well be a service running in Azure or any other .NET application.

Reference: Create Site Collections in SharePoint Online using CSOM

3

I know you asked for CSOM, but in case it helps anyone, I was able to do this in PowerShell using the CreateSite method of the Admin web service against on-prem SP2013. You can call DeleteSite similarly (it's simpler as it has only one parameter). I started out down the route of creating a tenant administration site for my on-prem SP2013 but was having authentication issues. This was a good fallback approach for me (does everything I need it to).

The inputs to the script are as follows:

  • $user - farm admin login (I am also using this as the owner of the new site collection)
  • $pwd - farm admin pwd
  • $adminSiteUrl - central admin site URL (must be accessible from the box where this script is running)
  • $siteUrl - the full URL of the new site collection to be created
  • $siteTitle - the title of the new site collection
  • $username - the display name of the new site collection owner

Here's the PowerShell:

$securePwd = ConvertTo-SecureString $pwd -AsPlainText -Force
$cred = New-Object PSCredential($user, $securePwd)
$wsdlUrl = $adminSiteUrl + "/_vti_adm/Admin.asmx?WSDL"
$svc = New-WebServiceProxy -Uri $wsdlUrl -Credential $cred
$svc.CreateSite(
    $siteUrl,   # URL
    $siteTitle, # Title
    "",         # Description
    1033,       # LCID
    "STS#0",    # WebTemplate
    $user,      # Owner Login
    $userName,  # Owner Name
    "",         # Owner Email
    "",         # PortalUrl
    "")         # PortalName
1

They said on prem and CSOM. None of the answers here are what he asked.

Here are some methods that do what we need:

HttpWebRequest CreateSoapWebRequest() {
  HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(adminUrl + "/_vti_adm/Admin.asmx");
  webRequest.Headers.Add("SOAPAction", "http://schemas.microsoft.com/sharepoint/soap/CreateSite");
  webRequest.ContentType = "text/xml; charset=\"utf-8\"";
  webRequest.Method = "POST";
  webRequest.Credentials = new NetworkCredential(username, password);
  return webRequest;
}

XmlDocument CreateSoapEnvelope(string url, string title, string description, string user, string lcid, string webTemplate) {
  XmlDocument soapEnvelopeDocument = new XmlDocument();
  string soapEnv = string.Format(@"<?xml version=""1.0"" encoding=""utf-8""?>
    <soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""
                   xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
      <soap:Body>
        <CreateSite xmlns=""http://schemas.microsoft.com/sharepoint/soap/"">
          <Url>{0}</Url>
          <Title>{1}</Title>
          <Description>{2}</Description>
          <Lcid>{3}</Lcid>
          <WebTemplate>{4}</WebTemplate>
          <OwnerLogin>{5}</OwnerLogin>
          <OwnerName>{6}</OwnerName>
          <OwnerEmail/>
          <PortalUrl/>
          <PortalName/>
        </CreateSite>
      </soap:Body>
    </soap:Envelope>", url, title, description, lcid, webTemplate, user, user);
  Console.WriteLine("Create site collection soap request: {0}", soapEnv);
  soapEnvelopeDocument.LoadXml(soapEnv);
  return soapEnvelopeDocument;
}

void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest) {
  using (Stream stream = webRequest.GetRequestStream()) {
    soapEnvelopeXml.Save(stream);
  }
}

And you can use the code like this:

XmlDocument soapEnvelopeXml = CreateSoapEnvelope(
        yourUrl,
        yourTitle,
        yourDescription,
        yourUser,
        yourLcid,
        yourWebTemplate
      );
      HttpWebRequest webRequest = CreateSoapWebRequest();
      InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);
      IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);

      asyncResult.AsyncWaitHandle.WaitOne();

      using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult)) {
        using (StreamReader rd = new StreamReader(webResponse.GetResponseStream())) {
          Console.WriteLine(rd.ReadToEnd());
        }
      }
1
  • They did not say on-prem.
    – spDevAdmin
    Commented Jul 17, 2020 at 19:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.