You are here:   Blog
Register   |  Login

 

Jan 22

Written by: Michael Washington
1/22/2012 12:55 PM  RssIcon

image

When deploying a LightSwitch web based application, the easiest method is to use the Publishing Wizard. However, the server that will host the LightSwitch application has to have the prerequisites installed

LightSwitch creates a normal ASP.NET application that launces a Silverlight application, so it is possible to package in a way that allows a person to simply FTP it to a server, and then run a wizard through their web browser to configure it. This method is used by applications such as DotNetNuke and ADefHelpDesk for years.

img3

To demonstrate the wizard, we will start with the application covered in: Help Desk: An Advanced Visual Studio LightSwitch Application.

The Install Experience

The person wishing to run your application would first download the .zip file that contains the application that you first published to your local machine then added code for the install wizard.

You can download that file here: http://lightswitchhelpwebsite.com/Downloads.aspx.

image

The files are unzipped and placed into a directory on the server hard drive (for example, these files could be transferred by FTP to the server).

image

The web server (IIS) administration is used to create a web application entry.

image

The website is configured as an ASP.NET 4.0 application.

image

A database is created.

image

A database user with db_owner permission is created.

image

Next, you simply navigate to the website in a web browser.

The code detects that the database is not set up and a link to the install wizard shows.

image

The wizard will appear.

image

In order to update the web.config and to upload files; read, write, and create permission is required.

Note, press the button to check permissions at least twice due to the test file being temporarily blocked sometimes.

image

The account that needs the permission to the web folder is the account that the ASP.NET account is running under. If it is ApplicationPoolIdentity, see this post to configure permissions for that account.

image

The next screen allows the database to be configured. When this is successful, the web.config of the application is updated.

image

The final step runs the setup scripts to create the required ASP.NET membership provider database objects and the tables required for the application.

image

When the set-up is complete the confirmation box will appear.

image

The application will load.

image

The application will appear.

When users visit the web address of the application, it will automatically load normally because the code will detect that the database is already set-up.

The Web Installer Code

image

The first step was to replace the default.htm file that the LightSwitch Publish method deployed with a new file called Default.aspx.

We also add code to the App_Code directory, the .sql set-up scripts to the SQLScripts directory and a Verify folder. The other files and folders are part of the original application, and created by the LightSwitch Publishing Wizard. All of their code is compiled into assemblies (.dlls) and are contained in the bin directory.

 

    protected void Page_Load(object sender, EventArgs e)
    {
        silverlightControlHost.Visible = false;
        boolSetup = Utility.DatabaseReady();
        if (boolSetup)
        {
            silverlightControlHost.Visible = true;
        }
        else
        {
            lnkSetup.Visible = true;
        }
    }

 

This allows us to have code that will show the link to the installation wizard if the database is not set-up.

The wizard is simply a series of ASP.NET Panels that guide the user through each step. The following code is used to check the permissions:

 

    protected void btnCheckPermissions_Click(object sender, EventArgs e)
    {
        int intValidItems = 0;
        blPermissions.Items.Clear();
        //FolderCreate
        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);
        //FileCreate
        permissionItem = new ListItem();
        permissionItem.Text = String.Format("File Create - {0}", ((VerifyFileCreate()) ? "Passed" : "Failed"));
        permissionItem.Enabled = ((permissionItem.Text.Contains("Passed")) ? true : false);
        blPermissions.Items.Add(permissionItem);
        intValidItems = intValidItems + ((permissionItem.Text.Contains("Passed")) ? 1 : 0);
        //FileDelete
        permissionItem = new ListItem();
        permissionItem.Text = String.Format("File Delete - {0}", ((VerifyFileDelete()) ? "Passed" : "Failed"));
        permissionItem.Enabled = ((permissionItem.Text.Contains("Passed")) ? true : false);
        blPermissions.Items.Add(permissionItem);
        intValidItems = intValidItems + ((permissionItem.Text.Contains("Passed")) ? 1 : 0);
        //FolderDelete
        permissionItem = new ListItem();
        permissionItem.Text = String.Format("Folder Delete - {0}", ((VerifyFolderDelete()) ? "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);
        // Show the Continue button?
        btnPermissionsNext.Visible = ((intValidItems == 4) ? true : false);
    }
 

 

The following code updates the web.config:

 

    protected void btnDatabaseCheck_Click(object sender, EventArgs e)
    {
        bool boolCanConnectToDatabase = CanConnectToDatabase();
        btnDatabaseNext.Visible = boolCanConnectToDatabase;
        this.lblConnectionResults.Text = (boolCanConnectToDatabase) ? 
            "Connection Successful" : "Connection Error";
        // If connection was successful then write the connection 
        // string to the web.config to be used on the next wizard step
        if (boolCanConnectToDatabase)
        {
            System.Configuration.Configuration rootWebConfig = 
                System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
            System.Configuration.ConnectionStringSettings connString;
            connString = rootWebConfig.ConnectionStrings.ConnectionStrings["_IntrinsicData"];
            connString.ConnectionString = strConnection;
            rootWebConfig.Save();
        }
    }

The following code runs the .sql scripts to set-up the database:

 

  protected void btnDatabaseSetupNext_Click(object sender, EventArgs e)
    {
        if (!Utility.DatabaseReady())
        {
            try
            {
                // Process all the SQL Scripts   
                foreach (string SQLScript in arrSQLScriptsToRun)
                {
                    System.Configuration.Configuration rootWebConfig = 
                        System.Web.Configuration.WebConfigurationManager
                        .OpenWebConfiguration(Request.ApplicationPath);
                    System.Configuration.ConnectionStringSettings connString;
                    connString =
                        rootWebConfig.ConnectionStrings.ConnectionStrings["_IntrinsicData"];
                    SqlConnection conn = null;
                    try
                    {
                        // read file
                        string strFilePath = MapPath(String.Format(@"~/SQLScripts/{0}", SQLScript));
                        using (StreamReader sr = new StreamReader(strFilePath))
                        {
                            // Create new connection to database
                            conn = new SqlConnection(connString.ConnectionString);
                            conn.Open();
                            while (!sr.EndOfStream)
                            {
                                StringBuilder sb = new StringBuilder();
                                SqlCommand cmd = conn.CreateCommand();
                                while (!sr.EndOfStream)
                                {
                                    string s = sr.ReadLine();
                                    if (s != null && s.ToUpper().Trim().Equals("GO"))
                                    {
                                        break;
                                    }
                                    sb.AppendLine(s);
                                }
                                // Execute T-SQL against the target database
                                cmd.CommandText = sb.ToString();
                                cmd.CommandTimeout = 600;
                                cmd.ExecuteNonQuery();
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        this.Response.Write(String.Format("An error occured: {0}", 
                            ex.ToString()));
                    }
                    finally
                    {
                        // Close out the connection
                        //
                        if (conn != null)
                        {
                            try
                            {
                                conn.Close();
                                conn.Dispose();
                            }
                            catch (Exception ex)
                            {
                                this.Response.Write(
                                    String.Format(@"Could not close the connection.  Error was {0}",
                                    ex.ToString()));
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                lblDatabaseSetup.Text = ex.Message;
                return;
            }
        }
        mvSetupWizard.SetActiveView(vwComplete);
    }

 

Download The Code

Download the code at: http://lightswitchhelpwebsite.com/Downloads.aspx

Note

The upload will not work if Default.aspx is in the web address (such as http://localhost/samplehelpdesk/Default.aspx), configure Default.aspx as a default document in the IIS web server and use an address such as http://localhost/samplehelpdesk/.

6 comment(s) so far...


Gravatar

Re: A LightSwitch Web Installer Wizard

This is really kewl... I have been trying to create my own wizard and getting stuck creating tables from my SQL script... this sheads some light on that and gets me interested in LightSwitch also.

By sayitfast on   3/1/2012 2:33 PM
Gravatar

Re: A LightSwitch Web Installer Wizard

My desktop app will be for users who dont have a clue. This wizard would be ideal for my app. But, the user still needs to perform the ISS adminstration - correct? Or, does the wizard take care of all?

By Lucius on   4/11/2013 7:43 AM
Gravatar

Re: A LightSwitch Web Installer Wizard

@Lucius - Yes this tool would have to be enhanced to do the additinal tasks you have identified.

By Michael Washington on   4/11/2013 8:13 AM
Gravatar

Re: A LightSwitch Web Installer Wizard

Do you have any plans for enhancing it Michael?

By Lucius on   4/11/2013 8:44 AM
Gravatar

Re: A LightSwitch Web Installer Wizard

@Lucius - I plan to use if for my own projects but that code would not be reusable. I would not try to enhance this into some sort of framework. It would eat up all my time :)

By Michael Washington on   4/11/2013 12:00 PM
Gravatar

Re: A LightSwitch Web Installer Wizard

OK - Thanks Mike.

By Lucius on   4/11/2013 1:17 PM

Your name:
Gravatar Preview
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Security Code
CAPTCHA image
Enter the code shown above in the box below
Add Comment   Cancel 
Microsoft Visual Studio is a registered trademark of Microsoft Corporation / LightSwitch is a registered trademark of Microsoft Corporation