MOSS MVP

I've moved my blog to http://blog.falchionconsulting.com!. Please update your links. This blog is no longer in use--you can find all posts and comments at my new blog; I will no longer be posting to this site and comments have been disabled.

Friday, October 5, 2007

Set Local Site Directory

Way back one of the first commands I created was one which would allow you to set the Master Site Directory (gl-setmastersitedirectory). It turns out that because my company decided to have each division in it's own site collection that I also needed to be able to set the local site directory (http://[host]/_layouts/SiteDirectorySettings.aspx).

This one took me a minute to figure out what was involved as the disassembled code was a bit of a mess. After spending some time with it I realized it was actually quite simple - just a matter of setting some properties on the root SPWeb object. The core code, which identifies the properties that need to be set, is shown below:

   1: /// <summary>
   2: /// Writes to the web property bag.
   3: /// </summary>
   4: /// <param name="site">The site containing the site directory.</param>
   5: /// <param name="siteDirectoryLoc">The site directory location.</param>
   6: /// <param name="enforceNewListing">if set to <c>true</c> [enforce new listing].</param>
   7: /// <param name="entryRequirements">The entry requirements.</param>
   8: /// <param name="allowSiteCollectionCreation">if set to <c>true</c> [allow site collection creation].</param>
   9: private static void WriteToWebPropertyBag(SPSite site, string siteDirectoryLoc, bool enforceNewListing, SiteDirectoryEntryRequirements entryRequirements, bool allowSiteCollectionCreation)
  10: {
  11:  using (SPWeb rootWeb = site.RootWeb)
  12:  {
  13:   // Set the SiteID corresponding to the site housing the site directory.
  14:   if (rootWeb.AllProperties.ContainsKey("DefaultSiteDirectorySiteId"))
  15:   {
  16:    rootWeb.AllProperties["DefaultSiteDirectorySiteId"] =
  17:     site.ID.ToString("D", CultureInfo.InvariantCulture);
  18:   }
  19:   else
  20:   {
  21:    rootWeb.AllProperties.Add("DefaultSiteDirectorySiteId",
  22:            site.ID.ToString("D", CultureInfo.InvariantCulture));
  23:   }
  24:  
  25:   // Set the WebID corresponding to the site directory.
  26:   Guid webId;
  27:   GetSiteDirectoryId(site, siteDirectoryLoc, out webId);
  28:  
  29:   if (rootWeb.AllProperties.ContainsKey("DefaultSiteDirectoryWebId"))
  30:   {
  31:    rootWeb.AllProperties["DefaultSiteDirectoryWebId"] =
  32:     webId.ToString("D", CultureInfo.InvariantCulture);
  33:   }
  34:   else
  35:   {
  36:    rootWeb.AllProperties.Add("DefaultSiteDirectoryWebId",
  37:            webId.ToString("D", CultureInfo.InvariantCulture));
  38:   }
  39:  
  40:   // Remove the default location if specified.
  41:   if (rootWeb.AllProperties.ContainsKey("DefaultSiteDirectoryLocation"))
  42:   {
  43:    rootWeb.AllProperties.Remove("DefaultSiteDirectoryLocation");
  44:   }
  45:  
  46:   // Set the enforce new listings option.
  47:   if (rootWeb.AllProperties.ContainsKey(LocalSiteDirectoryConstants.EnforceNewListingForSites.ToString()))
  48:   {
  49:    rootWeb.AllProperties[LocalSiteDirectoryConstants.EnforceNewListingForSites.ToString()] =
  50:     enforceNewListing.ToString();
  51:   }
  52:   else
  53:   {
  54:    rootWeb.AllProperties.Add(LocalSiteDirectoryConstants.EnforceNewListingForSites.ToString(),
  55:            enforceNewListing.ToString());
  56:   }
  57:  
  58:   // Set the allow site collection creation option if self service site creation is enabled.
  59:   if (site.WebApplication.SelfServiceSiteCreationEnabled)
  60:   {
  61:    if (rootWeb.AllProperties.ContainsKey(
  62:      LocalSiteDirectoryConstants.AllowSiteCollectionCreation.ToString()))
  63:    {
  64:     rootWeb.AllProperties[LocalSiteDirectoryConstants.AllowSiteCollectionCreation.ToString()] =
  65:      allowSiteCollectionCreation.ToString();
  66:    }
  67:    else
  68:    {
  69:     rootWeb.AllProperties.Add(LocalSiteDirectoryConstants.AllowSiteCollectionCreation.ToString(),
  70:             allowSiteCollectionCreation.ToString());
  71:    }
  72:   }
  73:   else if (allowSiteCollectionCreation)
  74:   {
  75:    throw new SPException("You must enable self service site creation via the central adminisration tool before you can allow site collection creation.");
  76:   }
  77:  
  78:   if (enforceNewListing)
  79:   {
  80:    // If we're enforcing new listings then set the directory entry requirements.
  81:    if (rootWeb.AllProperties.ContainsKey(LocalSiteDirectoryConstants.SiteDirectoryEntryRequirements.ToString()))
  82:    {
  83:     rootWeb.AllProperties[LocalSiteDirectoryConstants.SiteDirectoryEntryRequirements.ToString()] =
  84:      entryRequirements.ToString();
  85:    }
  86:    else
  87:    {
  88:     rootWeb.AllProperties.Add(
  89:      LocalSiteDirectoryConstants.SiteDirectoryEntryRequirements.ToString(),
  90:      entryRequirements.ToString());
  91:    }
  92:   }
  93:  
  94:   // Update the web with the specified properties.
  95:   rootWeb.Update();
  96:  }
  97: }
The syntax of the command, gl-setlocalsitedirectory, can be seen below.

C:\>stsadm -help gl-setlocalsitedirectory

stsadm -o gl-setlocalsitedirectory

Sets the local, or site collection, site directory.

Parameters:
        -siteurl <site collection url>
        -url <site directory url>
        [-enforcelistinginsitedir]
        [-sitedirentryrequirement <0=none, 1=at least one category, 2=all categories>]
        [-allowsitecollectioncreation]

Here's an example of how to set the site directory for a given site collection:

stsadm -o gl-setlocalsitedirectory -siteurl "http://intranet/hr" -url "/hr/SiteDirectory" -enforcelistinginsitedir -sitedirentryrequirement -allowsitecollectioncreation

4 comments:

Anonymous said...

Will this allow me to specify a custom virtual directory name?

Gary Lapointe said...

It works exactly the same as if you were to do it via the browser. The site directory specified must exist in the site collection.

brwalias said...

Gary,

I'm using extendvs to create a web application; however, there is no parameter to specify the virtual directory path. It currently appends the port being used but I would l like to change that to something else.

Thanks!

Gary Lapointe said...

There's currently no way to do that via stsadm. Looking at the code that is being executed when you do it via the browser it seems fairly simple - only problem is that Microsoft is using an internal method to create the web app (use the SPWebApplicationBuilder class for your own code - see below). Here's the code that Microsoft uses:

protected void BtnSubmit_Click(object sender, EventArgs e)
{
string str;
string str2;
SPLongOperation operation;
SPWebApplication application;
if (base.IsValid)
{
str = "/_admin/applicationcreated.aspx";
str2 = null;
operation = new SPLongOperation(this);
operation.Begin();
application = null;
application = SPWebApplication.CreateDefaultInstance(SPWebService.ContentService, Guid.NewGuid(), this.ApplicationPoolSection.Name, this.ApplicationPoolSection.IdentityType, this.ApplicationPoolSection.UserName, this.ApplicationPoolSection.Password, this.IisWebSiteSection.IisWebSiteDescription, this.IisWebSiteSection.IisWebSiteSecureSocketsLayer, this.IisWebSiteSection.IisWebSiteHostHeader, this.IisWebSiteSection.IisWebSitePort, this.IisWebSiteSection.IisWebSiteAllowAnonymous, this.IisWebSiteSection.IisWebSitePath, this.IisWebSiteSection.Uri, this.IisWebSiteSection.IisWebSiteDisableKerberos, true, this.ContentDatabaseSection.DatabaseServer, this.ContentDatabaseSection.DatabaseName, this.ContentDatabaseSection.DatabaseUserName, this.ContentDatabaseSection.DatabasePassword, this.ContentDatabaseSection.SearchServiceInstance, false, true);
application.Provision();
if (SPFarm.Local.TimerService.Instances.Count > 1)
{
new SPWebApplicationProvisioningJobDefinition(application, this.ApplicationPoolSection.ResetIis) { Schedule = new SPOneTimeSchedule(DateTime.Now) }.Update();
}
}
else
{
return;
}
SPAdministrationWebApplication local = SPAdministrationWebApplication.Local;
if (local != null)
{
local.RemoveAdministrativeTask("WSSCreateWebApplication");
}
str2 = SPHttpUtility.UrlKeyValueEncode("WebApplicationId", application.Id.ToString());
if (this.ApplicationPoolSection.ResetIis)
{
str2 = str2 + "&" + SPHttpUtility.UrlKeyValueEncode("IisReset", string.Empty);
}
operation.End(str, SPRedirectFlags.UseSource | SPRedirectFlags.Static, this.Context, str2);
}

I wouldn't try to match what they did though because they are using an internal method - this post has a code sample that will do it for you (I may try to rework this into a command if I have time): http://forums.microsoft.com/TechNet/ShowPost.aspx?PostID=1238244&SiteID=17