So you’ve got a content database (perhaps you used the gl-createcontentdb command) and now you want to create a site collection in that database. Problem is that you can’t do this easily via the browser and you definitely can’t do it via stsadm. There is a createsiteinnewdb command and a createsite command but the first will create a new database and the second will put the site collection in the “best match” database. But you need it in a specific database. What I decided to do was to create a new command: gl-createsiteindb.

The code is pretty straight forward – the bulk of the code is just validation code:

  1using System;
  2using System.Collections.Specialized;
  3using System.IO;
  4using System.Text;
  5using System.Web.Configuration;
  6using Lapointe.SharePoint.STSADM.Commands.SPValidators;
  7using Microsoft.SharePoint;
  8using Microsoft.SharePoint.Administration;
  9using Lapointe.SharePoint.STSADM.Commands.OperationHelpers;
 10
 11namespace Lapointe.SharePoint.STSADM.Commands.SiteCollectionSettings
 12{
 13   public class CreateSiteInDB : SPOperation
 14   {
 15       protected SPWebApplication m_WebApplication;
 16
 17       /// <summary>
 18       /// Initializes a new instance of the <see cref="CreateSiteInDB"/> class.
 19       /// </summary>
 20       public CreateSiteInDB()
 21       {
 22           SPParamCollection parameters = new SPParamCollection();
 23           parameters.Add(new SPParam("url", "url", true, null, new SPUrlValidator()));
 24           parameters.Add(new SPParam("lcid", "lcid", false, "0", new SPRegexValidator("^[0-9]+$")));
 25           parameters.Add(new SPParam("sitetemplate", "st", false, null, new SPNullOrNonEmptyValidator()));
 26           parameters.Add(new SPParam("title", "t", false, null, null));
 27           parameters.Add(new SPParam("description", "desc", false, null, null));
 28           parameters.Add(new SPParam("ownerlogin", "ol", false, null, new SPNonEmptyValidator()));
 29           parameters.Add(new SPParam("ownername", "on", false, null, null));
 30           parameters.Add(new SPParam("owneremail", "oe", true, null, new SPRegexValidator(@"^[^ \r\t\n\f@]+@[^ \r\t\n\f@]+$")));
 31           parameters.Add(new SPParam("quota", "quota", false, null, new SPNullOrNonEmptyValidator()));
 32           parameters.Add(new SPParam("hostheaderwebapplicationurl", "hhurl", false, null, new SPUrlValidator()));
 33           parameters.Add(new SPParam("secondarylogin", "sl", false, null, new SPNullOrNonEmptyValidator()));
 34           parameters.Add(new SPParam("secondaryname", "sn", false, null, null));
 35           parameters.Add(new SPParam("secondaryemail", "se", false, null, null));
 36           parameters.Add(new SPParam("dbname", "db", true, null, new SPNonEmptyValidator(), "Please specify the database name."));
 37
 38           StringBuilder sb = new StringBuilder();
 39           sb.Append("\r\n\r\nCreates a new site collection in an existing content database.\r\n\r\nParameters:");
 40           sb.Append("-url <url>");
 41           sb.Append("\r\n\t-owneremail <someone@example.com>");
 42           sb.Append("\r\n\t[-ownerlogin <DOMAIN\\name>]");
 43           sb.Append("\r\n\t[-ownername <display name>]");
 44           sb.Append("\r\n\t[-secondaryemail <someone@example.com>]");
 45           sb.Append("\r\n\t[-secondarylogin <DOMAIN\\name>");
 46           sb.Append("\r\n\t[-secondaryname <display name>]");
 47           sb.Append("\r\n\t[-lcid <language>]");
 48           sb.Append("\r\n\t[-sitetemplate <site template>]");
 49           sb.Append("\r\n\t[-title <site title>]");
 50           sb.Append("\r\n\t[-description <site description>]");
 51           sb.Append("\r\n\t[-hostheaderwebapplicationurl <web application url>]");
 52           sb.Append("\r\n\t[-quota <quota template>]");
 53           sb.Append("\r\n\t-dbname <content database name>");
 54           
 55           Init(parameters, sb.ToString());
 56       }
 57
 58       #region ISPStsadmCommand Members
 59
 60       /// <summary>
 61       /// Gets the help message.
 62       /// </summary>
 63       /// <param name="command">The command.</param>
 64       /// <returns></returns>
 65       public override string GetHelpMessage(string command)
 66       {
 67           return HelpMessage;
 68       }
 69
 70       /// <summary>
 71       /// Runs the specified command.
 72       /// </summary>
 73       /// <param name="command">The command.</param>
 74       /// <param name="keyValues">The key values.</param>
 75       /// <param name="output">The output.</param>
 76       /// <returns></returns>
 77       public override int Execute(string command, StringDictionary keyValues, out string output)
 78       {
 79           output = string.Empty;
 80
 81           
 82
 83           string dbname = Params["dbname"].Value;
 84
 85           string uriString = Params["url"].Value;
 86           string webTemplate = Params["sitetemplate"].Value;
 87           string title = Params["title"].Value;
 88           string description = Params["description"].Value;
 89           string ownerName = Params["ownername"].Value;
 90           string ownerEmail = Params["owneremail"].Value;
 91           string quota = Params["quota"].Value;
 92           string secondaryContactName = Params["secondaryname"].Value;
 93           string secondaryContactEmail = Params["secondaryemail"].Value;
 94           bool isHostHeaderWebAppUrlTypedIn = Params["hostheaderwebapplicationurl"].UserTypedIn;
 95           uint nLCID = uint.Parse(Params["lcid"].Value);
 96           Uri uri = new Uri(uriString);
 97           SPUrlZone zone = SPUrlZone.Default;
 98           bool createActiveDirectoryAccounts = m_WebApplication.WebService.CreateActiveDirectoryAccounts;
 99           string ownerLogin = Utilities.TryGetNT4StyleAccountName(Params["ownerlogin"].Value, m_WebApplication);
100           string secondaryContactLogin = null;
101           if (!createActiveDirectoryAccounts || !Params["secondaryemail"].UserTypedIn)
102           {
103               if (!createActiveDirectoryAccounts && Params["secondarylogin"].UserTypedIn)
104               {
105                   secondaryContactLogin = Utilities.TryGetNT4StyleAccountName(Params["secondarylogin"].Value, m_WebApplication);
106               }
107           }
108           else
109           {
110               secondaryContactLogin = @"@\@";
111           }
112
113           SPContentDatabase database = null;
114           foreach (SPContentDatabase tempDB in m_WebApplication.ContentDatabases)
115           {
116               if (tempDB.Name.ToLower() == dbname.ToLower())
117               {
118                   database = tempDB;
119                   break;
120               }
121           }
122           if (database == null)
123               throw new SPException("Content database not found.");
124
125           if (database.MaximumSiteCount <= database.CurrentSiteCount)
126               throw new SPException("The maximum site count for the specified database has been exceeded.  Increase the maximum site count or specify another database.");
127
128           SPSite site = null;
129           try
130           {
131               site = database.Sites.Add(uri.OriginalString, title, description, nLCID, webTemplate, ownerLogin,
132                   ownerName, ownerEmail, secondaryContactLogin, secondaryContactName, secondaryContactEmail,
133                   isHostHeaderWebAppUrlTypedIn);
134
135
136               if (!string.IsNullOrEmpty(quota))
137               {
138                   using (SPSiteAdministration administration = new SPSiteAdministration(site.Url))
139                   {
140                       SPFarm farm = SPFarm.Local;
141                       SPWebService webService = farm.Services.GetValue<SPWebService>("");
142
143                       SPQuotaTemplateCollection quotaColl = webService.QuotaTemplates;
144                       administration.Quota = quotaColl[quota];
145                   }
146               }
147               if (!string.IsNullOrEmpty(webTemplate))
148               {
149                   using (SPWeb web = site.RootWeb)
150                   {
151                       web.CreateDefaultAssociatedGroups(ownerLogin, secondaryContactLogin, string.Empty);
152                   }
153               }
154               if (isHostHeaderWebAppUrlTypedIn && !m_WebApplication.IisSettings[zone].DisableKerberos)
155               {
156                   Console.WriteLine(SPResource.GetString("WarnNoDefaultNTLM", new object[0]));
157                   Console.WriteLine();
158               }
159           }
160           finally
161           {
162               if (site != null)
163                   site.Dispose();
164           }
165
166           return OUTPUT_SUCCESS;
167       }
168
169       /// <summary>
170       /// Validates the specified key values.
171       /// </summary>
172       /// <param name="keyValues">The key values.</param>
173       public override void Validate(StringDictionary keyValues)
174       {
175           base.Validate(keyValues);
176           string uriString = Params["url"].Value;
177
178           if (Params["quota"].UserTypedIn)
179           {
180               string quota = Params["quota"].Value;
181               SPFarm farm = SPFarm.Local;
182               SPWebService webService = farm.Services.GetValue<SPWebService>("");
183
184               SPQuotaTemplateCollection quotaColl = webService.QuotaTemplates;
185
186               if (quotaColl[quota] == null)
187               {
188                   throw new ArgumentException(SPResource.GetString("InvalidQuotaTemplateName", new object[0]));
189               }
190           }
191
192           m_WebApplication = ValidateWebApplication(this);
193           if (m_WebApplication == null)
194           {
195               throw new FileNotFoundException(SPResource.GetString("WebApplicationLookupFailed", new object[] { uriString }));
196           }
197           SPUrlZone zone = SPUrlZone.Default;
198           if (!m_WebApplication.WebService.CreateActiveDirectoryAccounts && !Params["ownerlogin"].UserTypedIn)
199           {
200               throw new ArgumentException(SPResource.GetString("NoADCreateRequiresOwnerLogin", new object[0]));
201           }
202           if (m_WebApplication.GetIisSettingsWithFallback(zone).AuthenticationMode == AuthenticationMode.Windows)
203           {
204               bool bIsUserAccount;
205               if (Params["ownerlogin"].UserTypedIn)
206               {
207                   string strLoginName = Utilities.TryGetNT4StyleAccountName(Params["ownerlogin"].Value, m_WebApplication);
208                   if (!Utilities.IsLoginValid(strLoginName, out bIsUserAccount))
209                   {
210                       throw new ArgumentException(SPResource.GetString("InvalidLoginAccount", new object[] { strLoginName }));
211                   }
212                   if (!bIsUserAccount)
213                   {
214                       throw new ArgumentException(SPResource.GetString("OwnerNotUserAccount", new object[0]));
215                   }
216               }
217               if (Params["secondarylogin"].UserTypedIn)
218               {
219                   string strLoginName = Utilities.TryGetNT4StyleAccountName(Params["secondarylogin"].Value, m_WebApplication);
220                   if (!Utilities.IsLoginValid(strLoginName, out bIsUserAccount))
221                   {
222                       throw new ArgumentException(SPResource.GetString("InvalidLoginAccount", new object[] { strLoginName }));
223                   }
224                   if (!bIsUserAccount)
225                   {
226                       throw new ArgumentException(SPResource.GetString("OwnerNotUserAccount", new object[0]));
227                   }
228               }
229           }
230       }
231
232
233
234
235       #endregion
236
237       internal static SPWebApplication ValidateWebApplication(SPOperation operation)
238       {
239           if (SPFarm.Local == null)
240           {
241               throw new SPException(SPResource.GetString("OperationInvalidInRemoteFarm", new object[0]));
242           }
243           SPWebApplication application;
244           string uriString = operation.Params["url"].Value;
245           bool isHostHeaderWebAppUrlTypedIn = operation.Params["hostheaderwebapplicationurl"].UserTypedIn;
246           Uri requestUri = new Uri(uriString);
247           if ((requestUri.Scheme != Uri.UriSchemeHttps) && (requestUri.Scheme != Uri.UriSchemeHttp))
248           {
249               throw new ArgumentException(SPResource.GetString("InvalidSiteName", new object[] { uriString }));
250           }
251           if (isHostHeaderWebAppUrlTypedIn)
252           {
253               Uri hostHeaderWebAppUrl = new Uri(operation.Params["hostheaderwebapplicationurl"].Value);
254               application = SPWebApplication.Lookup(hostHeaderWebAppUrl);
255               if (application == null)
256               {
257                   return application;
258               }
259               bool portMatchFound = false;
260
261               foreach (SPIisSettings iisSettings in application.IisSettings.Values)
262               {
263                   foreach (SPSecureBinding secureBinding in iisSettings.SecureBindings)
264                   {
265                       if (requestUri.Port == secureBinding.Port)
266                       {
267                           portMatchFound = true;
268                           break;
269                       }
270                   }
271
272                   if (!portMatchFound)
273                   {
274                       foreach (SPServerBinding serverBinding in iisSettings.ServerBindings)
275                       {
276                           if (requestUri.Port == serverBinding.Port)
277                           {
278                               portMatchFound = true;
279                               break;
280                           }
281                       }
282                   }
283                   if (portMatchFound)
284                       return application;
285               }
286               Console.WriteLine(SPResource.GetString("HostHeaderDoesNotMatchWebAppPort", new object[0]));
287               Console.WriteLine();
288           }
289           else
290               return SPWebApplication.Lookup(requestUri);
291
292           return application;
293       }
294
295   }
296}

The syntax of the command can be seen below:

C:\>stsadm -help gl-createsiteindb

stsadm -o gl-createsiteindb

Creates a new site collection in an existing content database.

Parameters:
        -url <url>        
        -owneremail <someone@example.com>        
        [-ownerlogin <DOMAIN\\name>]        
        [-ownername <display name>]        
        [-secondaryemail <someone@example.com>]        
        [-secondarylogin <DOMAIN\\name>        
        [-secondaryname <display name>]        
        [-lcid <language>]        
        [-sitetemplate <site template>]        
        [-title <site title>]        
        [-description <site description>]        
        [-hostheaderwebapplicationurl <web application url>]        
        [-quota <quota template>]        
        -dbname <content database name>

The following table summarizes the command and its various parameters:

Command NameAvailabilityBuild Date
gl-createsiteindbWSS 3, MOSS 2007Released: 1/31/2008, Updated: 4/30/2009
Parameter NameShort FormRequiredDescriptionExample Usage
urlYesThe URL to the site collection to create.-url "http://portal/sites/NewSite"
owneremailoeYesThe site owner’s e-mail address. Must be valid e-mail address, in the form someone@example.com.-owneremail someone@example.com, -oe someone@example.com
ownerloginolIf your farm does not have Active Directory account creation mode enabled, then this parameter is required. This parameter should not be provided if your farm has Active Directory account creation mode enabled, as Microsoft Office SharePoint Server 2007 will automatically create a site collection owner account in Active Directory based on the owner e-mail address.The site owner’s user account. Must be a valid Windows user name, and must be qualified with a domain name, for example, domain\name-ownerlogin domain\name, -ol domain\name
ownernameonNoThe site owner’s display name.-ownername "Gary Lapointe", -on "Gary Lapointe"
secondaryemailseNoThe secondary site owner’s e-mail address. Must be valid e-mail address, in the form someone@example.com.-secondaryemail someone@example.com, -se someone@example.com
secondaryloginslIf your farm does not have Active Directory account creation mode enabled, then this parameter is required. This parameter should not be provided if your farm has Active Directory account creation mode enabled, as Microsoft Office SharePoint Server 2007 will automatically create a site collection owner account in Active Directory based on the owner e-mail address.The secondary site owner’s user account. Must be a valid Windows user name, and must be qualified with a domain name, for example, domain\name-secondarylogin domain\name, -sl domain\login
secondarynamesnNoThe secondary site owner’s display name.-secondaryname "Pam Lapointe", -sn "Pam Lapointe"
lcidNoA valid locale ID, such as “1033” for English. You must specify this parameter when using a non-English template.-lcid 1033
sitetemplatestNoSpecifies the type of template to be used by the newly created site. The value must be in the form name#configuration. If you do not specify the configuration, configuration 0 is the default (for example, STS#0). The list of available templates can be customized to include templates you create.-sitetemplate STS#0, -st STS#0
titletNoThe title of the new site collection-title "New Site"
descriptiondescNoDescription of the site collection.-description "New Site Description", -desc "New Site Description"
hostheaderwebapplicationurlhhurlNoA valid URL assigned to the Web application by using Alternate Access Mapping (AAM), such as “http://server_name”. When the hostheaderwebapplicationurl parameter is present, the value of the url parameter is the URL of the host-named site collection and value of the hostheaderwebapplicationurl parameter is the URL of the Web application that will hold the host-named site collection.-hostheaderwebapplicationurl http://newsite, -hhurl http://newsite
quotaNoThe quota template to apply to sites created on the virtual server.-quota Portal
dbnamedbYesThe name of the Microsoft SQL Server database or Microsoft SQL Server 2000 Desktop Engine (Windows) (WMSDE) database used for Windows SharePoint Services data.-dbname SharePoint_Content1, -db SharePoint_Content1

Here’s an example of how to create a site in an existing content database:

stsadm -o gl-createsiteindb -url "http://intranet/sites/testsite1" -owneremail "someone@domain.com" -ownerlogin "domain\someone" -ownername "Some User" -sitetemplate "BLANKINTERNET#2" -title "Test Site" -dbname "SharePoint_ContentDB1"

Update 4/30/2009: I’ve updated the code so that it now creates the default site groups for the site collection.