Introduction
The
DotNetNuke project contains a time tested set-up wizard that works in a lot of situations. You can use a
Web Deployment Project, but it requires you to run an installer on the server. This may not work for a lot of situations where you are using a shared hosting server. This wizard allows you to FTP the application to a remote server and then launch the configuration wizard from the web browser.
This example provides a C# version of the wizard and encapsulates it into one page to allow you to easily customize it.
The Application
When the user opens the first page of the application that is not set-up, they see this screen:
This is shown because the following code attempts to connect to the database using the LINQ to SQL Data Context that uses the database connection settings in the web.config. If it is able to connect, it then attempts to count the records in the Users table. The database may exist, but the Users table may not. Both need to exist for the set-up to be considered complete. You could insert code to check for a version number in a table. This will allow the wizard to run in upgrade situations.
protected void Page_Load(object sender, EventArgs e)
{
lnkSetup.Visible = !CanConnectToDatabase();
lnkWebApplication.Visible = !lnkSetup.Visible;
}
private bool CanConnectToDatabase()
{
bool CanConnect = true;
try
{
DataClassesDataContext DataClassesDataContext =
new DataClassesDataContext();
var result = from Users in DataClassesDataContext.Users
select Users;
int intCount = result.Count();
}
catch (Exception e)
{
string strError = e.Message;
CanConnect = false;
}
return CanConnect;
}
The link will take the user to the first page of the wizard:
The DotNetNuke application requires the ability to create directories and upload files on the server. The next page of the wizard allows the user to perform a permissions check.
The following method calls a series of methods that perform each check. If all checks are passed, the Continue to Next Step button is displayed.
protected void btnCheckPermissions_Click(object sender, EventArgs e)
{
int intValidItems = 0;
blPermissions.Items.Clear();
ListItem permissionItem = new ListItem();
permissionItem.Text = String.Format("Folder Create - {0}",
((VerifyFolderCreate()) ? "Passed" : "Failed"));
permissionItem.Enabled =
((permissionItem.Text.Contains("Passed")) ? true : false);
blPermissions.Items.Add(permissionItem);
intValidItems = intValidItems +
((permissionItem.Text.Contains("Passed")) ? 1 : 0);
permissionItem = new ListItem();
permissionItem.Text = String.Format("File Create - {0}",
((VerifyFolderCreate()) ? "Passed" : "Failed"));
permissionItem.Enabled =
((permissionItem.Text.Contains("Passed")) ? true : false);
blPermissions.Items.Add(permissionItem);
intValidItems = intValidItems +
((permissionItem.Text.Contains("Passed")) ? 1 : 0);
permissionItem = new ListItem();
permissionItem.Text = String.Format("File Delete - {0}",
((VerifyFolderCreate()) ? "Passed" : "Failed"));
permissionItem.Enabled =
((permissionItem.Text.Contains("Passed")) ? true : false);
blPermissions.Items.Add(permissionItem);
intValidItems = intValidItems +
((permissionItem.Text.Contains("Passed")) ? 1 : 0);
permissionItem = new ListItem();
permissionItem.Text = String.Format("Folder Delete - {0}",
((VerifyFolderCreate()) ? "Passed" : "Failed"));
permissionItem.Enabled =
((permissionItem.Text.Contains("Passed")) ? true : false);
blPermissions.Items.Add(permissionItem);
intValidItems = intValidItems +
((permissionItem.Text.Contains("Passed")) ? 1 : 0);
lblPermissionCheck.Text = String.Format("Permissions {0}",
((intValidItems == 4) ? "Passed" : "Failed"));
lblPermissionCheck.BackColor =
((intValidItems == 4) ? Color.Green : Color.Red);
btnPermissionsNext.Visible = ((intValidItems == 4) ? true : false);
}
The next screen allows the user to configure the database connection and test it:
LINQ to SQL provides a DatabaseExists()
method to easily indicate if the connection works:
private bool CanConnectToDatabase()
{
string strUserInfo = (!chkIntegrated.Checked) ?
String.Format("Persist Security Info=True;User ID={0};Password={1}",
this.txtUserId.Text, this.txtPassword.Text) : "Integrated Security=True";
strConnection = String.Format("Data Source={0};Initial Catalog={1};{2}",
this.txtServer.Text, this.txtDatabase.Text, strUserInfo);
DataClassesDataContext DataClassesDataContext =
new DataClassesDataContext(strConnection);
return DataClassesDataContext.DatabaseExists();
}
If the connection does exist, it is stored in the web.config:
if (boolCanConnectToDatabase)
{
System.Configuration.Configuration rootWebConfig =
System.Web.Configuration.WebConfigurationManager.
OpenWebConfiguration(Request.ApplicationPath);
System.Configuration.ConnectionStringSettings connString;
if (rootWebConfig.ConnectionStrings.ConnectionStrings.Count > 0)
{
connString =
rootWebConfig.ConnectionStrings.ConnectionStrings[
"WebInstallerConnectionString"];
if (connString != null)
{
connString.ConnectionString = strConnection;
rootWebConfig.Save();
}
}
}
The next page of the wizard checks to see if the Users table has already been created (the person may be running the wizard simply to fix the web.config after moving the SQL server). If the table exists, it allows the user to move to the next step. If it does not exist, it indicates that the Continue button will run the .sql set-up script.
#region Database Set-up
private void SetupDatabase()
{
DatabaseReady = TableExists();
lblDatabaseSetup.Text = (DatabaseReady) ?
"The Database is already set-up. Click continue."
: "Click the Continue button to run the database set-up scripts.";
}
private bool TableExists()
{
bool CanConnect = true;
try
{
DataClassesDataContext DataClassesDataContext =
new DataClassesDataContext();
var result = from Users in DataClassesDataContext.Users
select Users;
int intCount = result.Count();
}
catch (Exception e)
{
string strError = e.Message;
CanConnect = false;
}
return CanConnect;
}
protected void btnDatabaseSetupNext_Click(object sender, EventArgs e)
{
if (!TableExists())
{
try
{
string strSqlScript = GetSQLScript();
DataClassesDataContext DataClassesDataContext =
new DataClassesDataContext();
DataClassesDataContext.ExecuteCommand(strSqlScript);
}
catch (Exception ex)
{
lblDatabaseSetup.Text = ex.Message;
return;
}
}
mvSetupWizard.SetActiveView(vwComplete);
}
private String GetSQLScript()
{
string strSQLScript;
string strFilePath = MapPath(@"~/SQLScripts/Setup.sql");
StreamReader reader = new StreamReader(strFilePath);
strSQLScript = reader.ReadToEnd();
reader.Close();
reader = null;
return strSQLScript;
}
#endregion
The last page of the wizard contains a button to return the user back to the first page of the application:
Now, the program detects that the application is set-up correctly:
Points of Interest
- The user must create the database before running the wizard. While you could create the database on set-up, most shared hosting servers do not allow you this permission. Requiring the database to be set-up beforehand works in all situations.
- This set-up does not support SQL Server express in File mode. The DotNetNuke install wizard does, so you can find the code to do that in the DotNetNuke source code.
- This wizard only supports Microsoft SQL server. The sample script only works with SQL Server 2005. It can be altered to support SQL Server 2000.
Updates
- I opened a stream reader in the original code but did not close it! Bad programmer! It is fixed now.