Self-Service Site Provisioning using Apps for SharePoint 2013


NOTE: Site Provisioning using apps has been better addressed by myself and others in the community on the Office AMS project published on codeplex. You are highly encouraged to reference that material over this. I would also discourage the use of Autohosted apps for this type of customization. Thanks!

 

I’ve always been a big fan of self-service site provisioning in SharePoint.  That process is even better in SharePoint 2013 (including SharePoint Online), with the ability to specify a custom site creation form.  Owning the provisioning process is incredibly powerful for farm/tenant administrators to configure the options and outputs of site provisioning.  By leveraging the new app model, we can customize the provision process in SharePoint Online to activate specific features, capabilities, and branding to our sites.  This post will explore the process for delivering custom site creation using an app for SharePoint.  The video below demonstrates the solution outlined in this post.

[View:https://www.youtube.com/watch?v=WTN0zQN4enc]

Self-Service Sites in SharePoint 2013

Self-service provisioning is improved in SharePoint 2013 by allowing an administrator to specify a custom creation form.  This form can take over the provisioning process and will be the cornerstone of the solution outlined below.  Without implementing a custom form, the default form only allows a user to specify a title.  The default output will be a Team site created as a sub-site at a specified location.  Again, if we want to capture additional details or provide different options, we must introduce a custom creation form.

Default Create a Site form in SharePoint 2013

The Solution

Because the app needs the ability to create sub-sites and site collections anywhere in the tenancy, it will need FullControl permission on the entire tenancy.  The app will also need to make app-only calls to SharePoint, so it can work with tenant objects or sites outside the context.  Both these settings can be configured in the Permissions tab of the AppManifest.xml.

AppManifest Permissions for out App

 

NOTE: You should typically avoid requesting tenancy permissions in your apps…especially with FullControl.  It is a best practice for apps to request the minimum permissions they need to function.  The “tenancy” permission scope is in place specifically for scenarios like provisioning.  Tenancy-scoped apps will typically be developed in-house, as I would be REALLY surprised if the Office Store accepted an app requesting Tenant FullControl permissions.

 

Our app will enable administrators to dynamically configure site creation settings using a Library in the app web.  I’m using a library instead of a list, so each option can be displayed in the site creation form with an icon.  Each row in the Library will represent a site provisioning option for an end-user.  The columns to support this include the following:

  • Title – the title of the configuration option (ex: Small Team Site)
  • Site Template – the WebTemplate name to be used in provisioning (ex: STS#0 for Team Site)
  • Base Path – the absolute URL where this option will get provisioned (ex: https://tenant/teams/)
  • Site Type – choice of “Subsite” or “Site Collection”
  • MasterPage URL – url of the masterpage file to apply (leave blank for no branding)
  • Storage Maximum Limit – the storage quota in MB (only applicable for site collections)
  • UserCode Maximum Limit – the user code quota in points (only applicable for site collections)

Library Configuration in App Project

I leveraged a module in the solution to pre-load a few provisioning options, but an administrator could easily edit these options or add new options through the library.

Module Elements.xml to pre-load provisioning options

<?xml version=”1.0″ encoding=”utf-8″?>
<Elements xmlns=”http://schemas.microsoft.com/sharepoint/“>
  <Module Name=”AppAssets”>
    <File Path=”AppAssets\Blog.png” Url=”SSConfig/Blog.png” ReplaceContent=”TRUE”>
      <Property Name=”Title” Value=”Blog” Type=”string”></Property>
      <Property Name=”SiteTemplate” Value=”BLOG#0″ Type=”string”></Property>
      <Property Name=”BasePath” Value=”https://richdizzcom.sharepoint.com/sites/Blogs/” Type=”string”></Property>
      <Property Name=”SiteType” Value=”Subsite” Type=”string”></Property>
      <Property Name=”MasterPageUrl” Value=”/sites/Blogs/_catalogs/masterpage/DallasMTC.com.master” Type=”string”></Property>
      <Property Name=”StorageMaximumLevel” Value=”100″ Type=”string”></Property>
      <Property Name=”UserCodeMaximumLevel” Value=”300″ Type=”string”></Property>
    </File>
    <File Path=”AppAssets\Community.png” Url=”SSConfig/Community.png” ReplaceContent=”TRUE”>
      <Property Name=”Title” Value=”Community” Type=”string”></Property>
      <Property Name=”SiteTemplate” Value=”COMMUNITY#0″ Type=”string”></Property>
      <Property Name=”BasePath” Value=”https://richdizzcom.sharepoint.com/sites/Communities/” Type=”string”></Property>
      <Property Name=”SiteType” Value=”Subsite” Type=”string”></Property>
      <Property Name=”MasterPageUrl” Value=”/sites/Communities/_catalogs/masterpage/DallasMTC.com.master” Type=”string”></Property>
      <Property Name=”StorageMaximumLevel” Value=”100″ Type=”string”></Property>
      <Property Name=”UserCodeMaximumLevel” Value=”300″ Type=”string”></Property>
    </File>
    <File Path=”AppAssets\Project.png” Url=”SSConfig/Project.png” ReplaceContent=”TRUE”>
      <Property Name=”Title” Value=”Project” Type=”string”></Property>
      <Property Name=”SiteTemplate” Value=”PROJECTSITE#0″ Type=”string”></Property>
      <Property Name=”BasePath” Value=”https://richdizzcom.sharepoint.com/teams/” Type=”string”></Property>
      <Property Name=”SiteType” Value=”Site Collection” Type=”string”></Property>
      <Property Name=”MasterPageUrl” Value=”https://richdizzcom.sharepoint.com/_catalogs/masterpage/DallasMTC.com.master” Type=”string”></Property>
      <Property Name=”StorageMaximumLevel” Value=”100″ Type=”string”></Property>
      <Property Name=”UserCodeMaximumLevel” Value=”300″ Type=”string”></Property>
    </File>
    <File Path=”AppAssets\Publishing.png” Url=”SSConfig/Publishing.png” ReplaceContent=”TRUE”>
      <Property Name=”Title” Value=”Publishing” Type=”string”></Property>
      <Property Name=”SiteTemplate” Value=”BLANKINTERNET#0″ Type=”string”></Property>
      <Property Name=”BasePath” Value=”https://richdizzcom.sharepoint.com/sites/” Type=”string”></Property>
      <Property Name=”SiteType” Value=”Site Collection” Type=”string”></Property>
      <Property Name=”MasterPageUrl” Value=”https://richdizzcom.sharepoint.com/_catalogs/masterpage/DallasMTC.com.master” Type=”string”></Property>
      <Property Name=”StorageMaximumLevel” Value=”100″ Type=”string”></Property>
      <Property Name=”UserCodeMaximumLevel” Value=”300″ Type=”string”></Property>
    </File>
    <File Path=”AppAssets\Team.png” Url=”SSConfig/Team.png” ReplaceContent=”TRUE”>
      <Property Name=”Title” Value=”Team” Type=”string”></Property>
      <Property Name=”SiteTemplate” Value=”STS#0″ Type=”string”></Property>
      <Property Name=”BasePath” Value=”https://richdizzcom.sharepoint.com/teams/” Type=”string”></Property>
      <Property Name=”SiteType” Value=”Site Collection” Type=”string”></Property>
      <Property Name=”MasterPageUrl” Value=”https://richdizzcom.sharepoint.com/_catalogs/masterpage/DallasMTC.com.master” Type=”string”></Property>
      <Property Name=”StorageMaximumLevel” Value=”100″ Type=”string”></Property>
      <Property Name=”UserCodeMaximumLevel” Value=”300″ Type=”string”></Property>
    </File>
  </Module>
</Elements>

 

Our app will deliver a site creation form that will query the library to display site creation options.

PageLoad and btnCreate Events

private List<SSConfig> configList;
private const string SHAREPOINT_PID = “00000003-0000-0ff1-ce00-000000000000”;
private const string TENANT_ADMIN_URL = “https://richdizzcom-admin.sharepoint.com“;
protected void Page_Load(object sender, EventArgs e)
{
    //get SharePoint context
    var spContext = Util.ContextUtil.Current;
    using (var clientContext = TokenHelper.GetClientContextWithContextToken(spContext.ContextDetails.AppWebUrl, spContext.ContextDetails.ContextTokenString, Request.Url.Authority))
    {
        //populate the badges control
        List list = clientContext.Web.Lists.GetByTitle(“SSConfig”);
        CamlQuery query = new CamlQuery()
        {
            ViewXml = “<View><ViewFields><FieldRef Name=’Title’ /><FieldRef Name=’SiteTemplate’ /><FieldRef Name=’BasePath’ /><FieldRef Name=’SiteType’ /><FieldRef Name=’MasterPageUrl’ /><FieldRef Name=’StorageMaximumLevel’ /><FieldRef Name=’UserCodeMaximumLevel’ /></ViewFields></View>”
        };
        var items = list.GetItems(query);
        clientContext.Load(items, i => i.IncludeWithDefaultProperties(j => j.DisplayName));
        clientContext.ExecuteQuery();
        configList = items.ToList(spContext.ContextDetails.AppWebUrl, “SSConfig”);
    }

    if (!this.IsPostBack)
    {
        //bind repeater
        repeaterTemplate.DataSource = configList;
        repeaterTemplate.DataBind();

        //configure buttons based on display type
        if (Page.Request[“IsDlg”] == “1”)
            btnCancel.Attributes.Add(“onclick”, “javascript:closeDialog();return false;”);
        else
            btnCancel.Click += btnCancel_Click;
    }
}

protected void btnCancel_Click(object sender, EventArgs e)
{
    Response.Redirect(Page.Request[“SPHostUrl”]);
}

protected void btnCreate_Click(object sender, EventArgs e)
{
    //get the selected config
    SSConfig selectedConfig = configList.FirstOrDefault(i => i.Title.Equals(hdnSelectedTemplate.Value));
    if (selectedConfig != null)
    {
        string webUrl = “”;
        if (selectedConfig.SiteType.Equals(“Site Collection”, StringComparison.CurrentCultureIgnoreCase))
            webUrl = CreateSiteCollection(selectedConfig);
        else
            webUrl = CreateSubsite(selectedConfig);

        //redirect to new site
        ClientScript.RegisterStartupScript(typeof(Default), “RedirectToSite”, “navigateParent(‘” + webUrl + “‘);”, true);
    }
}

 

Once the user submits the site creation form, the app will provision differently based on site type (Subsite or Site Collection).  One thing that is common between the two methods is the need to execute app-only calls, since we will likely be provisioning with a different context from where the form is hosted (ex: site collection will require the context of the tenant administration site).  The TokenHelper contains a GetAppOnlyAccessToken method to get the access token for a specific site that is different from the context of the form.

To provision a sub-site, we need to establish context with the site that will host our new sub-site (ie – the parent site).  To apply a brand to a sub-site, I’m requiring the master page to exist in the Master Page Gallery of the root web in the site collection.  That way, I can just set the MasterUrl and CustomMasterUrl after the new sub-site is provisioned.

Code to create sub-site

private string CreateSubsite(SSConfig selectedConfig)
{
    string webUrl = selectedConfig.BasePath + txtUrl.Text;

    //create subsite
    var parentSite = new Uri(selectedConfig.BasePath);  //static for my tenant
    var token = TokenHelper.GetAppOnlyAccessToken(SHAREPOINT_PID, parentSite.Authority, null).AccessToken;
    using (var clientContext = TokenHelper.GetClientContextWithAccessToken(parentSite.ToString(), token))
    {
        var properties = new WebCreationInformation()
        {
            Url = txtUrl.Text,
            Title = txtTitle.Text,
            Description = txtDescription.Text,
            WebTemplate = selectedConfig.SiteTemplate,
            UseSamePermissionsAsParentSite = false
        };

        //create and load the new web
        Web newWeb = clientContext.Web.Webs.Add(properties);
        clientContext.Load(newWeb, w => w.Title);
        clientContext.ExecuteQuery();

        //TODO: set additional owners

        //apply the masterpage to the site (if applicable)
        if (!String.IsNullOrEmpty(selectedConfig.MasterUrl))
        {
            newWeb.MasterUrl = selectedConfig.MasterUrl;
            newWeb.CustomMasterUrl = selectedConfig.MasterUrl;
        }

        /**************************************************************************************/
        /*   Placeholder area for updating additional settings and features on the new site   */
        /**************************************************************************************/

        //update the web with the new settings
        newWeb.Update();
        clientContext.ExecuteQuery();
    }

    return webUrl;
}

 

Provisioning a site collection is a little more complex.  First we need to establish context with tenant administration site and use a Tenant object for creation.  The Tenant object can be found in the Microsoft.Online.SharePoint.Client.Tenant assembly which comes with the SharePoint Online Management Shell download.  Provisioning the site collection can take a while to complete, so this occurs asynchronously using the SpoOperation class.  We can leverage this to wait until the creation operation is complete before trying to apply the master page.  Applying a master page to a site collection is a little more complex.  The master page needs to live within the site collection, so our solution will download the master page from the location referenced in the configuration and upload it into the Master Page Gallery of the new site collection before setting MasterUrl and CustomMasterUrl on the site.  This requires that scripts and styles in the master page are referenced using absolute paths.  Pulling down and applying an entire design package would likely be a more elegant, but was overkill for this proof of concept.

Code to create site collection

private byte[] GetMasterPageFile(string masterUrl)
{
    byte[] mpBytes = null;

    //get the siteurl of the masterpage
    string siteUrl = masterUrl.Substring(0, masterUrl.IndexOf(“/_catalogs”));

    var siteUri = new Uri(siteUrl);  //static for my tenant
    var token = TokenHelper.GetAppOnlyAccessToken(SHAREPOINT_PID, siteUri.Authority, null).AccessToken;
    using (var clientContext = TokenHelper.GetClientContextWithAccessToken(siteUri.ToString(), token))
    {
        string relativeMasterUrl = masterUrl.Substring(8);
        relativeMasterUrl = relativeMasterUrl.Substring(relativeMasterUrl.IndexOf(“/”));
        File file = clientContext.Web.GetFileByServerRelativeUrl(relativeMasterUrl);
        var stream = file.OpenBinaryStream();
        clientContext.ExecuteQuery();
        using (stream.Value)
        {
            mpBytes = new Byte[stream.Value.Length];
            stream.Value.Read(mpBytes, 0, mpBytes.Length);
        }
    }

    return mpBytes;
}

private string CreateSiteCollection(SSConfig selectedConfig)
{
    string webUrl = “”;

    //create site collection using the Tenant object
    var tenantAdminUri = new Uri(TENANT_ADMIN_URL);  //static for my tenant
    var token = TokenHelper.GetAppOnlyAccessToken(SHAREPOINT_PID, tenantAdminUri.Authority, null).AccessToken;
    using (var clientContext = TokenHelper.GetClientContextWithAccessToken(tenantAdminUri.ToString(), token))
    {
        var tenant = new Tenant(clientContext);
        webUrl = String.Format(“{0}{1}”, selectedConfig.BasePath, txtUrl.Text);
        var properties = new SiteCreationProperties()
        {
            Url = webUrl,
            Owner = “ridize@richdizzcom.onmicrosoft.com“,
            Title = txtTitle.Text,
            Template = selectedConfig.SiteTemplate,
            StorageMaximumLevel = Convert.ToInt32(selectedConfig.StorageMaximumLevel),
            UserCodeMaximumLevel = Convert.ToDouble(selectedConfig.UserCodeMaximumLevel)
        };
        SpoOperation op = tenant.CreateSite(properties);
        clientContext.Load(tenant);
        clientContext.Load(op, i => i.IsComplete);
        clientContext.ExecuteQuery();

        //check if site creation operation is complete
        while (!op.IsComplete)
        {
            //wait 30seconds and try again
            System.Threading.Thread.Sleep(30000);
            op.RefreshLoad();
            clientContext.ExecuteQuery();
        }
    }

    //get the newly created site collection
    var siteUri = new Uri(webUrl);  //static for my tenant
    token = TokenHelper.GetAppOnlyAccessToken(SHAREPOINT_PID, siteUri.Authority, null).AccessToken;
    using (var clientContext = TokenHelper.GetClientContextWithAccessToken(siteUri.ToString(), token))
    {
        var newWeb = clientContext.Web;
        clientContext.Load(newWeb);
        clientContext.ExecuteQuery();

        //update description
        newWeb.Description = txtDescription.Text;

        //TODO: set additional site collection administrators

        //apply the masterpage to the site (if applicable)
        if (!String.IsNullOrEmpty(selectedConfig.MasterUrl))
        {
            //get the the masterpage bytes from it’s existing location
            byte[] masterBytes = GetMasterPageFile(selectedConfig.MasterUrl);
            string newMasterUrl = String.Format(“{0}{1}/_catalogs/masterpage/ssp.master”, selectedConfig.BasePath, txtUrl.Text);
                   
            //upload to masterpage gallery of new web and set
            List list = newWeb.Lists.GetByTitle(“Master Page Gallery”);
            clientContext.Load(list, i => i.RootFolder);
            clientContext.ExecuteQuery();
            FileCreationInformation fileInfo = new FileCreationInformation();
            fileInfo.Content = masterBytes;
            fileInfo.Url = newMasterUrl;
            Microsoft.SharePoint.Client.File masterPage = list.RootFolder.Files.Add(fileInfo);
            string relativeMasterUrl = newMasterUrl.Substring(8);
            relativeMasterUrl = relativeMasterUrl.Substring(relativeMasterUrl.IndexOf(“/”));

            //we can finally set the masterurls on the newWeb
            newWeb.MasterUrl = relativeMasterUrl;
            newWeb.CustomMasterUrl = relativeMasterUrl;
        }

        /**************************************************************************************/
        /*   Placeholder area for updating additional settings and features on the new site   */
        /**************************************************************************************/

 

        //update the web with the new settings
        newWeb.Update();
        clientContext.ExecuteQuery();
    }

    return webUrl;
}

 

 

 

Because our site creation form will be launch in the “Start a Site” dialog, our app needs to be able to communicate back with the SharePoint page that hosts the dialog.  This communication is necessary to make the dialog page visible, resize the dialog, close the dialog, and navigate away from the dialog.  This cross-domain communication is achieved using the HTML5 postMessage API, where SharePoint “listens” for MakePageVisible, Resize, CloseDialog, and NavigateParent messages from the page displayed within the dialog IFRAME.  Below are the scripts to implement this messaging, which I hunted down through thousands of line of javascript.

postMessage scripts for interacting with dialog parent

//Makes the page visible in the dialog
function MakeSSCDialogPageVisible() {
    var dlgMadeVisible = false;
    try {
        var dlg = window.top.g_childDialog;
        if (Boolean(window.frameElement) && Boolean(window.frameElement.makeVisible)) {
            window.frameElement.makeVisible();
            dlgMadeVisible = true;
        }
    }
    catch (ex) {
    }
    if (!dlgMadeVisible && Boolean(top) && Boolean(top.postMessage)) {
        var message = “MakePageVisible”;
        top.postMessage(message, “*”);
    }
}

//Resizes the dialog for the page size
function UpdateSSCDialogPageSize() {
    var dlgResized = false;
    try {
        var dlg = window.top.g_childDialog;
        if (!fIsNullOrUndefined(dlg)) {
            dlg.autoSize();
            dlgResized = true;
        }
    }
    catch (ex) {
    }
    if (!dlgResized && Boolean(top) && Boolean(top.postMessage)) {
        var message = “PageWidth=450;PageHeight=480”;
        top.postMessage(message, “*”);
    }
}

//postMessage to SharePoint for closing dialog
function closeDialog() {
    var target = parent.postMessage ? parent : (parent.document.postMessage ? parent.document : undefined);
    target.postMessage(‘CloseDialog’, ‘*’);
}

//postMessage to close the dialog and navigate from the page to a specified url
function navigateParent(url) {
    var target = parent.postMessage ? parent : (parent.document.postMessage ? parent.document : undefined);
    target.postMessage(‘NavigateParent=’ + url, ‘*’);
}

 

In order for our site creation form to launch from the “add site” link on the “sites” page, we need to configure it as the “Start a Site” form in the tenant administration site.  This field is limited to 255 characters, so we will likely need to remove some of the standard tokens that are passed to our app.  At minimum, the URL MUST include SPHostUrl and SPAppWebUrl parameters.  Our app will leverage these to get context and access tokens from SharePoint.

“Start a Site” configuration in SharePoint admin center

Our app should now be ready for primetime!  Here is a screenshot of our custom app launched from the “Start a Site” dialog and in full-screen mode.

Our custom provisioning app launched from the “Create a Site” link

The fullscreen version of the app

Final Thoughts

I hope this post helped illustrate the power of delivering self-service site creation and how the app model can take it to the next level.  I see this and “App Stapling” as the primary two patterns for pushing capability/features into sites and site collections in SharePoint Online.  Please note that the provided code is not production ready and also references on of my tenants.

Solution code: http://sdrv.ms/XSBX7n

Comments (91)

  1. Anonymous says:

    Just in time! I just found out how to use the tenant CSOM. This example is great!

    What type of project is SelfServiceProvisioning, I can't open it in my VS2012?

  2. It uses the "App for SharePoint" template that is part of the new Office/SharePoint tooling.  You can get it here: aka.ms/OfficeDevToolsForVS2012

    You will also need the SharePoint Online Management Shell if you want to provision site collections…you can find that here: http://www.microsoft.com/…/details.aspx

    Hope that helps…let me know if you have any other questions!

  3. Anonymous says:

    I was using 11.0.50901.0, that's why I could open the example! 11.0.60226.0 works great!

  4. Anonymous says:

    Great post and very interesting as I'm just now getting up to speed with all you can do in Office 365.  Where do you find the SharePoint product id (SHAREPOINT_PID) that you reference in your code example?  Thanks!

  5. Kevin…that SHAREPOINT_PID is the same for ALL SharePoint online tenants:

    00000003-0000-0ff1-ce00-000000000000

    If you are interested, you can find it as part of the "Microsoft.SharePoint" app identifier here:

    https://[tenant].sharepoint.com/_layouts/15/appprincipals.aspx

  6. Anonymous says:

    Hi, I have spoken to alot of people and consultants and were unable to get any assistance on how to setup SP 2013 for multiple tenants. Have you got any guidance with regards to this? BTW – Love this app.

  7. Anonymous says:

    Hi,

    Thank you for the app.  I am having a problem with it recognizing the master page. I am creating a publishing site (I changed that template elements.xml to create a sub-site instead of a site collection). I changed the master page value to "mysitename.sharepoint.com/…/oslo.master". I get an invalid URL error. If I go to the master pages gallery and hover on the oslo.master in its view properties, the URL is equal to what I put in the elements.xml file. The site is created just fine. It just blows up when trying to update the new web MasterURL. Any ideas?

    Thanks for your help!

  8. Anonymous says:

    Very interesting article. Is there a way to automatically deploy an app on personal sites on O365.

    This would be great to change the default look end feel  for end users.

  9. Anonymous says:

    Hello Richard,

    If i deploy this solution to my own on-premise SharePoint farm it states that this app doesn't work in my farm. How is this possible and how can i make this app work for my on-premise farm?

  10. Anonymous says:

    In addition to my previous post i deleted the Web Site prerequisites and then i can update the app. Only then the default.aspx is looping in the            

    var spContext = Util.ContextUtil.Current;

    Section in the default.aspx.cs

               get

               {

                   ContextUtil spContext = null;

                   if (HttpContext.Current.Request.Cookies["SPContext"] != null)

                   {

                       JavaScriptSerializer serializer = new JavaScriptSerializer();

                       spContext = new ContextUtil((SPContext)serializer.Deserialize(HttpContext.Current.Request.Cookies["SPContext"].Value, typeof(SPContext)));

                   }

                   if (spContext == null || !spContext.IsValid)

                       spContext = new ContextUtil(HttpContext.Current.Request);

                   if (spContext.IsValid)

                       return spContext;

                   else

                   {

                       HttpContext.Current.Response.Redirect(GetRedirectUrl()); <<

                       return null;

                   }

               }

    The page hangs upon 'HttpContext.Current.Response.Redirect(GetRedirectUrl());' because the context cannot be filled??

  11. Bert – in an on-premise deployment, you will likely be leveraging a high-trust S2S app.  In this model, OAuth does NOT use a context token, but instead can create access tokens using a certificate it shares with the farm.  The TokenHelper has methods to get SPContext using S2S, so you would need to likely change the ContextUtil accordingly.  If you haven't built a high-trust app, I highly recommend you create a simple "hello world" example before trying to convert this solution.  The following MSDN article should help you: msdn.microsoft.com/…/fp179901.aspx

  12. Anonymous says:

    I'm getting "token request failed" exceptions at                

    oauth2Response =

                       client.Issue(AcsMetadataParser.GetStsUrl(targetRealm), oauth2Request) as OAuth2AccessTokenResponse;

    in tokenhelper.cs when I attempt to provision a site.

    Would you have any idea what I'm doing wrong? This is obviously a configuration issue, but the only changes that I've made have been to swap out your tenant with my own.

  13. Anonymous says:

    @ Jim Crowley – Do you have the Realm configured in your web.config?

  14. Anonymous says:

    ive gotten the app to deploy, but sites are not being created.  how can i find out my realm id?

  15. Anonymous says:

    Got it – once deployed to the dev site (or whichever site you deploy to) you can find the client id and realm at "/sites/dev/_layouts/15/appprincipals.aspx".  You will then see a pipe-delimited value.  The realm id is the value after the @ sign.

  16. Anonymous says:

    Great post @Richard diZerega,

    is it also possible to customize the provisioning process of My Sites / Personal Sites, e.g. to automatically set a custom master page or composed look?

    Thanks in advance!

  17. Christian – I'd recommend you look at the following post by Vesa Juvonen…it demonstrates how to do similar things with personal sites: blogs.msdn.com/…/customizing-sharepoint-2013-personal-sites-using-sp-apps-with-remote-provisioning.aspx

    -Richard

  18. Anonymous says:

    It works great, but there is one problem that I cannot seem to circumvent …

    I put my app URL into the SharePoint settings in the online admin. It opens and the data I fill in posts, but no site was created. I used bit.ly to shorten the url

    guid.o365apps.net/…/Default.aspx

    When I use the URL directly into the browser and fill in data the app works great… any pointers?

    I guess there is something to do with context, but I cannot wrap my head around it

    Same scenario even when I deploy it from apps or deploy it from a site collection…

  19. Anonymous says:

    I am needing help RE the Realm ID and the Client ID required in the Web.config

    Using steps from this comment section I got the string that "@john" mentioned.

    In the web.config file I see:

    So where do I add the string after the @ sign? as "ClientId" value?

    What about the value of "ClientSecret"

    <appSettings>

       <add key="ClientId" value="" />

       <add key="ClientSecret" value="" />

     </appSettings>

  20. Anonymous says:

    OK, I am pretty lost at this point.

    After updating the project code to work with my tenant, I can upload the app to the catalog and / or I can deploy via VS 2012 to my developer site.

    The app will not create any sites or site collections.

    When I "Start Debugging" from VS 2012 my dev site shows the app as available and when I click "Trust It" the browser chugs along with the message "Working on it…".

    It has been "Working on it.." for 15 minutes now…

    Nothing else ever happens.

    I am sure my misunderstanding / misconfiguration is very basic, and I have not idea what it is or how to correct it.

    Anyone who could point me in the right direction?

    Thanks and Cheers   :0(

  21. SpaceGhost904 – You shouldn't have to update anything in the web.config…just the TENANT_ADMIN_URL constant pointing to your SharePoint admin site and the file details in the module that adds options to the list instance (ex: they likely point to masterpages and sites you don't have).  

    You can either A) debug the app directly from visual studio against a developer site (which will generate it's own ClientID and ClientSecret) or B) use upload the app to an app catalog.  I might recommend you start with debugging to see if you are getting any exceptions.

    Another thing to consider is that it can take 15min or more for a site collection to provision in SPO, so I would look in the SharePoint admin site to see if it has really started.

    Hope this helps,

    -Richard

  22. Anonymous says:

    @RicharddiZerega

    Thanks for the reply I know you are very busy.

    My issue(s) are resolved.

    I can now create sub sites and site collections as well.

    One minor issue I will be working on soon is that after a sub site is created the form just posts and renders "Default.aspx" again.

    I am going to develop a "Thank You" confirmation message as well…

    Also, after a Site Collection is created if "Default.aspx" is left open it errors out after a few minutes…

    Cheers,

  23. Anonymous says:

    BTW, I learned about your blog while at DevConn 2013

    OK, One last question / issue.

    I want to have more than 5 options and when I add any more images to the "AppAssets" folder and update the Elements.xml File to reflect the additional site provisioning choices.

    I can never get more than 5 options to appear on Default.aspx

    I can see that the images in the "AppAssets" folder populate (move) over to the SSConfig Document Library.

    No matter what I do the images I add to AppAssets are left behind in the "AppAssets" folder so do not move to the SSConfig library and do not appear as options on Default.aspx

    I really want 7 options and I realize I need to update the UI on Defualt.aspx to be wider as well.

    How do I add more than 5 images and related config settings to SSConfig?

    Please advise.

    Thanks in advance for all your help I know you must be very busy…

    Cheers

  24. Anonymous says:

    Hey I found my error in the Elements.xml file.

    Really dumb error…

    Cheers

  25. Anonymous says:

    Hi, First i want to thank you for the app. Im able to deploy this in SPO and able to create SiteCollections. One issue is after clicking on Create button the page goes in infinite loop and gets stuck in "Working On it". I verified in another tab, the site collection is created and working fine, but the dialog box never redirects to default page. Can you help me out.

  26. Anonymous says:

    Apparently MS might have changed something in O365 on or around 11/6/2013.

    The base code of this "Self-Service Site Provisioning App" had been creating sub sites fine in my tenant until 11/6/2013

    Now I get this error:

    Please note that I cannot debug in Visual Studio as when the App deployment gets to the stage where I would usually click "Trust" the browser just endless loops "Working on it" and then postsback real quick and then back to "Working on it"…

    Server Error in '/' Application.

    Value does not fall within the expected range.

     Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: Microsoft.SharePoint.Client.ServerException: Value does not fall within the expected range.

    Source Error:

    An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.  

    Stack Trace:

    [ServerException: Value does not fall within the expected range.]

      Microsoft.SharePoint.Client.ClientRequest.ProcessResponseStream(Stream responseStream) +1855

      Microsoft.SharePoint.Client.ClientRequest.ProcessResponse() +951

      Microsoft.SharePoint.Client.ClientRequest.ExecuteQueryToServer(ChunkStringBuilder sb) +623

      Microsoft.SharePoint.Client.ClientRequest.ExecuteQuery() +47

      Microsoft.SharePoint.Client.ClientRuntimeContext.ExecuteQuery() +89

      Microsoft.SharePoint.Client.ClientContext.ExecuteQuery() +294

      SelfServiceProvisioningWeb.Pages.Default.CreateSubsite(SSConfig selectedConfig) +498

      SelfServiceProvisioningWeb.Pages.Default.btnCreate_Click(Object sender, EventArgs e) +110

      System.Web.UI.WebControls.Button.OnClick(EventArgs e) +9555658

      System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +103

      System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10

      System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13

      System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +35

      System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1724

    Is anyone else getting this when creating sub sites?

    I can still create site collections, and, creation of sub sites is what we really need…

    Thanks in advance for all your help

  27. Anonymous says:

    SpaceGhost904, I began to get the same error. However, now the platform seems to have been fixed, and this works again.

  28. Anonymous says:

    I experienced exactly the same error when creating subsites SpaceGhost904 & Safka..

    I'll test if it runs again this afternoon & report back here.

  29. Anonymous says:

    nope, still experiencing the same error. And I can also not load my web templates

  30. Anonymous says:

    Ok, it's now 15:33 here and as of 10 minutes ago I'm not experiencing anymore server errors. That's a week of work wasted while figuring what was going wrong not counting evening and weekend work! Glad the 'problem' fixed itself. I also get the templates now so my code functions as it's supposed to now. Glad I checked back on this blog 🙂

    To the author of the article: Great article, really found the material I needed for my project, can't thank you enough 🙂

  31. Anonymous says:

    OK, Probably a stupid Newbie thing.

    I have been searching and attempting to resolve this issue for days now.

    Cannot debug "Self-Service Site Provisioning App" (Via Start >> Debug) in Visual Studio.

    The app loads in "/_layouts/15/AppInv.aspx" and I can click "Trust"…

    After that the app just endless loops "Working on it"…

    I am getting the error below over and over again:

    A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll

    An exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll but was not handled in user code

    A first chance exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' occurred in SelfServiceProvisioningWeb.dll

    A first chance exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' occurred in SelfServiceProvisioningWeb.dll

  32. Anonymous says:

    Not sure how to fix that SpaceGhost since I'm only using some of his subsite provisioning code. Have you tried using some breakpoints? And see how far you get? Have you enabled visual studio to break on uncaught exceptions?

    BTW: I've got the [ServerException: Value does not fall within the expected range.] a few more times today, very randomly..it's back to normal now.

    I suspect they are making changes trying to fix something for their tenant portal. It's been ongoing for about a week now..

  33. Anonymous says:

    with 'they' I mean whoever's working BTS @ microsoft. It's bad that such a thing happens on such a platform.

    My app is going in production in about a month or so. I can only hope this occurence doesn't keep repeating itself.

  34. Serge ARADJ says:

    Great post @Richard diZerega !

    I was just asking myself if one could adapt your solution to a SharePoint-Hosted App ? My goal is to get as close as possible to what we could do On-Prem, and I'd like to avoid any cloud-hosting solution…

    Thx.

  35. Anonymous says:

    Are there any possibilities for uploading a custom solution (wsp) before applying the site template and then use a custom web template?

  36. Anonymous says:

    @Pieterjan Spoelders  

    Yes I have attempted to set break point. Point is never hit.

    I will attempt to "enable visual studio to break on uncaught exceptions" next…

    Thanks

  37. Anonymous says:

    @Pieterjan Spoelders  

    Yes, I am using VS 2012 and it looks like "break on uncaught exceptions" was enabled already by default.

    Anyway, had intention of making this App Production ready but tabling that as I cannot even debug it.

    Thanks

  38. @Serge ARADJ – you can only provision site collections server-side and in O365.  However, you can provision subsites.  Don't let "cloud-hosted" freak you out…cloud-hosted apps can be hosted anywhere…including another IIS machine in your data center.  Utlimately cloud-hosted = server-side code without running on the SharePoint farm.

    @Evert – I haven't tried that scenario, but it seems feasible.

    @SpaceGhost904 – I'm not sure why you are unable to hit a breakpoint.  You might remove all the aync processing for now and do everything on the main thread.  To do this, you will likely want to increase timeouts for site collections to finish provisioning.

    -RZ

  39. Anonymous says:

    I can set breakpoints, but, I cannot get past what happens after I click the "Trust" button.

    In other words the App will not even load during a debug session.

    So, removing any code would not help as I am not able to even start the provisioning process at all.

    To debug am I supposed to be able to click start debugging (green arrow or F5) or is there some other configuration / setting I am supposed to do?

    Please help as I have a deadline and not being able to debug is very time consuming frustrating and a blocking issue.

    Thanks in advance for ANY guidance you or anyone else can provide…

    sure I am missing something very very basic.

    I lowered the permissions for the app to web and fullcontrol and even tried just write thinking my tenant just did not want to grant full tenant control.

    Am I not waiting long enough for the tenant to "Trust" the app?

    Still getting"

    An exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll but was not handled in user code

    A first chance exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' occurred in SelfServiceProvisioningWeb.dll

    A first chance exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' occurred in SelfServiceProvisioningWeb.dll

    A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll

    An exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll but was not handled in user code

    A first chance exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' occurred in SelfServiceProvisioningWeb.dll

    A first chance exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' occurred in SelfServiceProvisioningWeb.dll

    A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll

    An exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll but was not handled in user code

    A first chance exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedE

  40. Anonymous says:

    @RicharddiZerega

    Sorry I made the previous post.

    Close to being totally confused by my situation.

    Is it possible that something is wrong with our tenant?

    I am going to explain to our organization that App Model development is currently immature and we should wait a period of time to let it "mature"…

    Thanks and Cheers

  41. Anonymous says:

    @Pieterjan Spoelders  

    Good Day,

    Hey after you start debugging in VS 2012 does the "_layouts/15/AppRedirect.aspx?" page load with the "Trust It" button displayed?

    Does Default.aspx load after you click the "Trust it" button.

    I am so focused on understanding this, step by step, if that is what it takes, I am just going to keep hacking away on my own personal time…

    Cheers

  42. SpaceGhost904 – I wouldn't call the app model immature as much as a different approach.  I'm currently out of the country (Dubai/Brazil), but I'd be happy to have help you debug when I get back in the home next week.  If that sounds good…shoot me an email to richdizz at outlook dotcom.

  43. Anonymous says:

    @RicharddiZerega

    Thanks so much yes that would really help.

    I will shoot an email.

    Thanks so much again.

    I can customize the declarative parts of the app in the mean time.

    Cheers,

  44. Anonymous says:

    OK, finally got a breakpoint to be hit by setting it in “SelfServiceProvisioningweb.TokenHelper”.

    After I “Start Debugging” and then click the “Trust it” button on "/_layouts/15/AppInv.aspx"

    The code just keeps hitting the if statement below over and over and over again until I “Stop Debugging”.

    if (!validationSuccessful)

               {

                   throw new AudienceUriValidationFailedException(

                       String.Format(CultureInfo.CurrentCulture,

                       ""{0}" is not the intended audience "{1}"", String.Join(";", acceptableAudiences), token.Audience));

               }

               return token;

    I am so new to App Model development this is not telling me much.

    Hope it means something to anyone here.

    Thanks so much.

  45. Anonymous says:

    Me too facing the debug issue problem. Did anybody found the solution?

  46. Anonymous says:

    I'm quite sure something goes wrong with your validation then. Are you sure you added the realm property  to your web.config file  like so:     <appSettings>…<add key="Realm" value="realmvaluegoeshere"> </appSettings>?

  47. Anonymous says:

    @Pieterjan Spoelders

    This conflicts with guidance from "Richard diZerega".

    When I asked about adding the Realm ID to the Web.config file, Richard answered, see what I copied and pasted below.

    Are you saying that adding that value allowed you to debug?

    I have never been able to debug this App

    Richard diZerega: 30 Oct 2013 3:50 PM

    SpaceGhost904 – You shouldn't have to update anything in the web.config…just the TENANT_ADMIN_URL constant pointing to your SharePoint admin site and the file details in the module that adds options to the list instance (ex: they likely point to masterpages and sites you don't have).  

    You can either A) debug the app directly from visual studio against a developer site (which will generate it's own ClientID and ClientSecret) or B) use upload the app to an app catalog.  I might recommend you start with debugging to see if you are getting any exceptions.

    Another thing to consider is that it can take 15min or more for a site collection to provision in SPO, so I would look in the SharePoint admin site to see if it has really started.

    Hope this helps,

    -Richard

  48. Anonymous says:

    When i open the page in modal window(popup) the people picker wont work. I get error saying

    Sorry, we had some trouble accessing your site.

    FIX   Dismiss

    If the "Fix it" button doesn't solve the issue, click here for more information.

    I guess this has to do something with calling user profile services. I verified by debugging, this line wont execute properly

    context.executeQueryAsync(function () {

                           var results = context.parseObjectFromJsonString(searchResult.get_value());

  49. Anonymous says:

    When i click on create button the modal window just reloads the page again. No site/sub site is created. Even the textbox clear the values. But this works absolutely fine in normal window mode. Any help appreciated

  50. Anonymous says:

    Hi all,

    The images from the template selection section don't render correctly. Anyone an idea how to fix this?

    Thx

  51. @Raghu – have you tried debugging…can you hit a breakpoint?  I have not seen the issue you described, but it might be IE Security Zone related if you only see it with IE

    @Sveng – I am almost 100% sure your issue with images is IE Security Zone related.  I suspect images will display in Chrome/Firefox.  To fix, try adding the remote web url (or https://*o365apps.net) to trusted sites in IE.

    -richdizz

  52. Anonymous says:

    Hi Richard,

    Thank you for your quick response. Unfortunately, your suggestions didn't work. So when I publish the app, go to my form, the template selection images are not visible (displays as a cross)  – even as a trusted site. When I copy-paste the link of the image and open in a new tab, the image is available. From the moment that I hit the appweb and go back to the remoteweb – the image is visible. I guess it's something to do with authentication issues.

    Regards,

  53. Anonymous says:

    Richard,

    It was related to IE security zone issue. Resolved it.. Thanks a lot.

  54. @Sveng – Yes, it is an authentication issue due to the IE Security zones…if you turn on fiddler, you should be able to see login redirects on the picture requests.  If I had to build this app again, I wouldn't put the pictures in the app web, as what you are experienced is a VERY frequent problem (same with displaying profile pictures in an app).

    You say you put the remote web in trusted sites…make sure you put the app web and remote web in trusted sites as well.  IE Security zones block token sharing across zones.  🙁

    -Richard

  55. Anonymous says:

    Thank you Richard for your feedback again. Really appreciate it. Maybe I'll base64 encode the images and store the values into a SharePoint list within the app web.

    Regards,

  56. That's actually a really good idea Sveng…I might use that myself 🙂  IE Security Zones are kryptonite these days…

  57. Anonymous says:

    Adding the url https://*.o365apps.net as trusted sites resolved my postback issue as mentioned earlier. But I cannot ask all the users in the organization to follow the same procedure. Is there any alternative method to achieve this.

  58. Anonymous says:

    Hi,

    I am getting web.config error. How to resolve it.

    Thanks.

  59. Anonymous says:

    Adding the url https://*.o365apps.net as trusted sites resolved my postback issue as mentioned earlier. But I cannot ask all the users in the organization to follow the same procedure. Is there any alternative method to achieve this.

  60. Anonymous says:

    When i click on create button the modal window just reloads the page again. Even the text box clear the values. But this works absolutely fine in normal window mode. This is observed in only Safari browser on Windows 7(chrome, Firefox works fine. IE works fine after adding it in trusted zone) . Is there any setting i need to change in safari?

  61. Mohan Seenippandian says:

    This example is great. Is there are an API method to enable "external sharing"  for site collections ?

  62. Mohan Seenippandian says:

    got it,

    SiteProperties site = tenant.GetSitePropertiesByUrl(url, true);

    site.SharingCapability = SharingCapabilities.ExternalUserSharingOnly;

    Requires latest client dlls or the KB2817619 SDK update

  63. Anonymous says:

    I have 2 major issues, I cannot figure out how to add users correctly to the sites being created and the images will not show unless i view the library first then go back to the app. Can anyone help with these?

  64. Anonymous says:

    Hi Brandon, Code to add users

    private void AddUsersAsAdmin(ClientContext clientContext)

           {

               try

               {

                   var users = hdnAdministratorLogins.Value.Split('!');

                   for (int i = 0; i < users.Length; i++)

                   {

                       string login = users[i].ToString();

                       login = login.Replace("!", "");

                       User user = clientContext.Web.EnsureUser(login);

                       Web web = clientContext.Web;

                       Group ownerGrp = web.AssociatedOwnerGroup;

                       ownerGrp.Users.AddUser(user);

                       clientContext.ExecuteQuery();

                   }

               }

               catch

               {

                   Microsoft.SharePoint.Client.Utilities.Utility.LogCustomRemoteAppError(ErrorLogContext, new Guid("{6b3b9061-14e7-423f-a747-7a5613348a98}"), "Error in AddUsersAsAdmin");

                   ErrorLogContext.ExecuteQuery();

                   throw;

               }

           }

  65. Anonymous says:

    Im getting this error in error console of SAFARI BROWSER(5.1.7) when i open this app through my site link

    Blocked a frame with origin "https://763a65f1-26af-4fed-81c5-320da421cfc5.o365apps.net&quot; from accessing a frame with origin "https://test-my.sharepoint.com&quot;. Protocols, domains, and ports must match. (x3).  

    If i open it in normal mode window first and than through my site, it is working fine. But directly in my site it is not working Please help me. This is deployed in production.

  66. Anonymous says:

    I am a bit confused how this should work with SharePoint Online as there is no page load event to play with. Am I missing something, or is this only a solution for on-prem deployments?

  67. Anonymous says:

    I could really use some help with this. I am sure I am doing something silly. I am able to deploy this app to our SPO environment, and I am able to fill out the new site form. After I fill out the page to create a new Blog site (for example), I am able to see the new subsite listed in the site contents. If I try and go to the new subsite I simply just get "Sorry, something went wrong" with no further details and no way to get any additional details. It is so frustrating that something so simple has taken two days of my time so far.

  68. Anonymous says:

    Anybody experience the subsites being created but not redirected to the new site just back to the form? Thanks!

  69. Anonymous says:

    Hello,

    I created this App as an auto-hosted app in an Office365 developer site. I have granted it Full control on the Tenant. However, when I try to create a site collection I still get an access denied when executing the query after Tenant.CreateSite.

    What am I missing here?

    Kind Regards, Jurgen

  70. Anonymous says:

    Nevermind, I simply had to check the App-only calls box in Permissions tab in appmanifest….

  71. Anonymous says:

    I am able to search users but it keeps saying user search error after i create the site it makes the site, but does not add users to the owners group….can anyone help?

  72. Anonymous says:

    If anyone is having issues with the icons displaying you can use the friendlier URL and it seems to work fine. One way to get that is go to the settings and you will see the URL at the top. Remove 'SSConfig/Forms/AllItems.aspx' or whatever you called your list from the URL and the remaining string is the link you want to use to access the self service app.

  73. Anonymous says:

    Excellent work Richard, I have this working in SharePoint Online 2013 but I require one more thing. I'd like to create a site collection with a custom site template. I'm at the point where I've created the site collection and successfully uploaded a site template (wsp) file to the solutions gallery but at this point I can't see any way of activating the solution, do you have any idea how to do this?

  74. Terry – I'd highly recommend looking at the template solution Vesa Juvonen has blogged about.  Vesa and I are combining some of the IP of our respective solutions and hoping to put out a consolidated solution on codeplex in the future: blogs.msdn.com/…/site-provisioning-techniques-and-remote-provisioning-in-sharepoint-2013.aspx

    -RZ

  75. Anonymous says:

    Hello Richard,

    Greate article and solution.  I was wondering if this was able to also run on perm and how much effort there would be to do so.  We are unsure when/if we are moving to the cloud be if we can create an app like this and have the flexibility to run it in either platform….That would be ideal

    Thanks in advance

    John

  76. Anonymous says:

    Great solution. Only I'm getting the same error Alison mentioned a year ago, invalid url when the part that sets the masterpage hits. Has anybody else seen this error and fixed it?

    Thanks,

    Astrid

  77. Anonymous says:

    @Mohan: SiteProperties site = tenant.GetSitePropertiesByUrl(url, true);

    site.SharingCapability = SharingCapabilities.ExternalUserSharingOnly;

    The above code is not working even after installing latest dlls and  KB2817619 SDK update.

    Could you please share the location of dll?

  78. ———— IMPORTANT NOTE ————

    Site provisioning has been enhanced and can be found at http://officeams.codeplex.com

    ———— IMPORTANT NOTE ————

  79. Anonymous says:

    Hi Richard,

    Firstly, thanks for this great blog post!  I took the time to look through the AMS Apps and was wondering… what exactly has been enhanced in the new solution?  It seems like the solution you came up with your this article is a bit more complete.

    Thanks,

    Yohan

  80. Anonymous says:

    Hi, Richard

    How i can do with Sharepoint Hosted App? I need to provision a subsite with a especific site template or adding webparts and list programatically

    Thanks!

  81. Zuas – Office AMS has (or soon will have) a sample of subsite provisioning client-side. Check out for it at http://officeams.codeplex.com/

  82. Anonymous says:

    Thanks Richard, but the example of the AMS is to provisioning subsite from a Provider hosted app. That i want a create is a Sharepoint hosted app that includes something like site template and then provision that.

    I am looking a lot of days for a solution like this on internet and i dont found.

    The only solution that i see is install a site template manually and then call from the sharepoint hosted app, but is not like i am trying to create.

    What do you think of this? You see another way?

  83. Anonymous says:

    For anyone looking for a free on-prem solution to provide self-service site collection creation for either 2010 or 2013, we just released a Free edition of Site Provisioning and Governance Assistant (SPGA).  It is a traditional Farm Solution, not a SharePoint App such as the one provided by Richard in this article.  But, it achieves the objective of being able to provide a self-service solution (on-premises only) with things like support for different site templates, managed paths, approvals and quotas.  We also provide a premium version that does more (such as integrating with our SharePoint extranet solution), for a fee.  Learn more on our website at:  http://goo.gl/m5lv0E

    Jeff Cate

    Founder and President

    PremierPoint Solutions (formerly SharePoint Solutions)

  84. Anonymous says:

    In the step Start a site, the site settings does not save my changes to the URL. I Click "Use the form at this URL" paste in the URL of the App, but it does not save it. I don´t get any error.

  85. Anonymous says:

    I do agree with others asking for : SharePoint Provider Hosted!

    and bad news : autohosted not support anymore, so all the solution presented there is just deprecated 🙁

    msdn.microsoft.com/…/dn722449(v=office.15).aspx

    So could you do the same with Provider Hosted and still declarative SharePoint artifact ?

    i m quite sure it s not possible, need to do all with JSOM or CSOM

  86. Anonymous says:

    Hi and tnx for great App! Is there possible to get this working with SharePoint Hosted as Hosting Type?

  87. Anonymous says:

    Hi,

    I am getting access denied error while creating site collection even though I checked the " App Only call option" .Access denied. You do not have permission to perform this action

    or access this resource.

    Please let me know on this

  88. Anonymous says:

    Hi,

    Great post Richard. I just have one silly question..I couldn't find the code where you are creating the custom form i.e." start a new site" form.

  89. BijuJoseph says:

    I am trying to implement site/sub site provisioning using high trust app in SP 2013 (S2S). Is there a full sample that I can refer? My question are around how to create context for admin Url, Site Url when we user high trust apps. Which methods I should use to get the contexts? Please help.

  90. Sambit Kumar says:

    Hi,

    I am not able to download the sample code from one drive.Can you please help me here.