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:
1: using System;
2: using System.Collections.Specialized;
3: using System.IO;
4: using System.Text;
5: using System.Web.Configuration;
6: using Lapointe.SharePoint.STSADM.Commands.SPValidators;
7: using Microsoft.SharePoint;
8: using Microsoft.SharePoint.Administration;
9: using Lapointe.SharePoint.STSADM.Commands.OperationHelpers;
10:
11: namespace 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 Name | Availability | Build Date |
|---|---|---|
| gl-createsiteindb | WSS 3, MOSS 2007 | Released: 1/31/2008
Updated: 4/30/2009 |
| Parameter Name | Short Form | Required | Description | Example Usage |
|---|---|---|---|---|
| url | Yes | The URL to the site collection to create. | -url "http://portal/sites/NewSite" | |
| owneremail | oe | Yes |
The 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 |
| ownerlogin | ol |
If 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 |
| ownername | on | No |
The site owner's display name. |
-ownername "Gary Lapointe"
-on "Gary Lapointe" |
| secondaryemail | se | No |
The 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 |
| secondarylogin | sl |
If 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 |
| secondaryname | sn | No |
The secondary site owner's display name. |
-secondaryname "Pam Lapointe"
-sn "Pam Lapointe" |
| lcid | No |
A valid locale ID, such as "1033" for English. You must specify this parameter when using a non-English template. |
-lcid 1033 | |
| sitetemplate | st | No |
Specifies 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 |
| title | t | No |
The title of the new site collection |
-title "New Site" |
| description | desc | No |
Description of the site collection. |
-description "New Site Description"
-desc "New Site Description" |
| hostheaderwebapplicationurl | hhurl | No |
A 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 |
| quota | No |
The quota template to apply to sites created on the virtual server. |
-quota Portal | |
| dbname | db | Yes |
The 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.


