Category Archives: MVC 4

Create an installer for website with WIX, part 1

For a customer we created a new web application in MVC4 with an underlying SQL database. One of the requirements was to provide an installer to install this website at their customers local installations. The installer had to do a few tasks:

  • Install the .NET 4.5 framework if that isn’t installed already
  • Install the MVC 4 framework if that isn’t installed already.
  • Create a folder and copy all needed files to run the application
  • Create a new database on an existing SQL server and prefill the database with the correct tables and values. (the connection details and database name should be entered by the end user running the installer)
  • Create a new website in IIS 7.5 (create website and application pool running under .NET 4.5)
  • Alter the config file so the correct connection settings are used (entered by the end user)

From Visual Studio 2012 on there is no Windows Installer project available any more. You can use the InstallShield Express edition with limited capabilities or the Windows Installer XML (WiX) open source package created by Rob Mensching when he was working for Microsoft. (It’s actually the oldest open source project from Microsoft and now under the OuterCurve foundation)

The Installshield express version doesn’t support IIS installations and falls out of the boat. WiX does support all actions that we have to do but has a steep learning curve. I used WIX in a previous project and still had some hassle to put all of it together. This series of posts will walk us through the creation of the installer.

Start project

Start by downloading the WiX toolset from http://wixtoolset.org/releases/. For this demo I used the 3.8.826.0 version. This is not the latest stable published release but I haven’t got any problems with this version.

Next step is creating a MVC 4 web project and choose for an internet application so we have some default files (javascript, css, views, controllers, …).

Right click on the solution in the solution explorer and choose to add another project. In the ‘Add New Project’ dialog select Windows Installer XML on the left hand side. Choose for ‘Setup Project’ and click the OK button.

image

You should get a new project with only one file (Product.wxs).

WiX flow

WiX source files are written in XML and have the wxs or wxi (for variables) extensions. Those files have to be compiled to wixobj files. This can be done in Visual Studio or by command line by using the candle.exe tool in the WiX toolset. After compiling the wixobj files another tool is needed to create the msi (installer) file, the light.exe tool.

The most simple installer can be created by just using one wxs file. You will notice that it will make your project more clear to use different wxs files. One for every part of the installation.

You can use the default UI that is available in the WiX toolset but with bigger projects (and in this demo) you can create your own UI and flow. Even the UI is defined in XML and has the same wxs extension. Another reason to split up your installer code in different files to keep the overview.

Step 1: install all needed files

Open up the Product.wxs file in Visual Studio. You’ll see already a few standard values filled out.

At line 3 you get the product attributes that have to be set. Leave the asterix ( * ) at the Id tag. WiX will replace this with an unique Guid when compiling the source. Set the version, language and the name to the desired values.

IIS default location for websites is the c:\inetpub directory. We’ll alter the installer so this default location is used. In one of the next chapters we’ll be able to change this folder. Navigate to line 15 and alter the Directory tag.

You’ll see I’ve changed the default InstallFolder to Inetpub. (from c:\Program Files to c:\Inetpub). This is all we have to change for the install location.

On line 26 you’ll see the ComponentGroup where we’ll have to define all files that have to be installed in our installation folder. Let’s start with adding some files. In the example below I added 3 files in the root of out application (favicon.ico, web.config and global.asax). To add the bin folder I had to add a new ComponentGroup, a new Component, and a new Directory element before I could add the files (2 dll’s).

As you can see this is a tedious job to add every file you want to be installed. Luckily there is a faster way to create this.

Use the heat component from the WiX toolset

The WiX toolset has another tool heat.exe that can help us to harvest all files that we need to install. Although heat was incorporated in Votive (the Visual Studio environment for WiX) in earlier versions, in the 3.7 – 3.8 version this is not available in Visual Studio.

MSBuild to the rescue

If we want to make use of the heat component we’ll have to script it. We can create a bat file we can run every time before we build the installer or we can create an MS build script that we can run. The MS build script has the advantage that we can reuse this script for out build server (continuous integration).

Create a new text file in the Setup project and rename it to setup.build. First we’ll add some properties in a ‘PropertyGroup’: the source of our website and the name of the WiX file we want to build. We also include the path where we should publish all files. In the ‘itemgroups’ we define the temporary files witch is the content of the web site and the list of WiX input files.

Add build target

We first have to build our website so we are sure we have the latest build we are deploying. Therefor we add a target in the MS build file

Add Publish website target

We’ll use the build in publish feature of MS build to deploy the website to a new folder so we have only the files we need. (and not the .cs files etc)

Harvest the files in WiX

Now that we have all the files we need under a temporary folder we can use the heat.exe tool in the WiX tool belt to harvest the files and create a wxs file.

The parameters used in this command:

  • dir $(Publish) tells to harvest a directory (our published website)
  • -dr:  The directory where the files have to be installed to
  • -ke:  Keep the Empty directories
  • -srd:  Suppress harvesting the root directory as an element.
  • -cg: The ComponentGroup name that have to be used
  • -var var.publishDir: Will substitute the source directory with a wix variable so we can use $(var.publishDir)\myfile.txt in the wxs files
  • -out $(WebsiteContentCode)  the file we want to be created (see PropertyGroup settings)

Test the script

With the heat command inserted we can test our script. Open up a Developer Command Prompt for VS2012. Change the prompt to the DemoWebsite.Setup project folder and type the following command:

msbuild /t: Build;PublishWebsite;Harvest setup.build

and hit enter. If everything goes well you’ll see a lot of command coming by. The script will create a folder Setup\publish under the root and publish the website. At last a WebsiteContent.wxs file will be created in the setup project folder.

If you open up the WebsiteContent.wxs file you’ll see all files and folders are added with their own Id under a ComponentGroup MyWebComponents.

If you looked closely you’ll have seen a few WiX commands passing by when executing the build file. Because we are going to handle the WiX build process in our build file we can exclude the setup project from the build configuration. Right click on the solution in the Solution Explorer in Visual Studio and choose for Configuration manager.

image

Change the active solution configuration to ‘Release’ and uncheck the build flag next to the setup project.

image

Update the Product.wxs file

Now we have all our files we have to install we have to reference to the created MyWebComponents CompenentGroup and delete the entries we made before to add the files.

Build the installer

Now that we have all the components for the first fase (installing the files) we can use the candle.exe and light.exe tools from the WiX tool belt to built our installer.

Add properties in the build file

First we need some more properties in our build file. Add the WebSiteContentObject parameter that will hold the compiled WiX code (WebSiteContent.wixobj). And also add the MsiOut parameter that will hold the path and name of the installer (.msi) file.

Add candle.exe in the build file

Add a new target tag in the build file and add the candle.exe tool with the parameters where to find the publish directory and witch files he has to compile.

Add light.exe in the build file

In the same target (WIX) add the light.exe command with parameters where to put the generated msi and witch source files to include.

Final run

Open up your Developer Command Prompt and type the next command where we added the WIX target:

msbuild /t: Build;PublishWebsite;Harvest;WIX setup.build

Hit enter and keep your fingers crossed. If you had no error messages you should find a msi file in the bin/release folder of the setup project. Run that installer and you’ll see that under the C:\inetpub folder a DemoWebsite folder is added with all the published files from our webapplication.

If you had any errors you can find the complete files here:

Next parts

Enough for one blog post I would say. the next posts in this series will handle the next actions:

  • Install the .NET 4.5 framework if that isn’t installed already
  • Install the MVC 4 framework if that isn’t installed already.
  • Create a folder and copy all needed files to run the application (done)
  • Create a new database on an existing SQL server and prefill the database with the correct tables and values. (the connection details and database name should be entered by the end user running the installer)
  • Create a new website in IIS 7.5 (create website and application pool running under .NET 4.5)
  • Alter the config file so the correct connection settings are used (entered by the end user)

Complete source code

You can find the complete source code for this project on GitHub. Keep in mind that this project will be altered when the next parts are implemented. I will try to keep the commits together with the series.

Other posts in this series

Creating a JIRA interface in 1-2-3

For one of our projects where close to the first test release. While preparing the necessary documents (test overview, legal documents, bug report, …) I felt a bit ashamed to give the client a Word document to report bugs to us. For a software development company it’s a bit shameful to let the client fill out a paper, scan it, mail it and then have someone copy the document in our issue tracker.

While driving home I thought it couldn’t be that difficult to set up a small site where the client can report the bugs. But I didn’t want to create a new bug tracker nor give the client direct access to our issue tracker (JIRA from Confluence).

JIRA has a API that you can address to create and fetch issues from their tracker. But I didn’t want to  spend a couple of hours implementing the REST service. (jeah, I know, lazy as hell)

Nuget to the rescue

When I got home, the first thing I checked was the nuget site to see if anyone had already created a package to communicate with the JIRA API. First thing that showed up in the search was Atlassian.SDK a complete package, even including a Linq Query implementation to search for issues created by Federico Silva Armas.

image

Great, let’s get started.

New MVC 4 web application

I fired up Visual Studio 2012 and choose a new MVC 4 Default application with Razor support. Opened up the Package Manager Console and ran the following command:

Add controller

I added a new controller in the controllers folder and named it HomeController. In the Index method I’ve added the call to JIRA to fetch all items from a certain filter.

The implementation is really simple, create a new Jira object with as parameters the URL to your JIRA instance, a username and a password. (in the constructor)
In the Index method you then can call GetIssuesFromFilter and add the filtername as parameter. The advantage of using a filter is that you can always change this filter settings if you want to remove certain issues from the result without to change anything in your application.

You’ll need off course the user rights correctly set in JIRA to access the issues that are returned from the filter.

Add View

Next I created a new view under the Views – Home folder using the add view action after a right click on the folder. Create a strongly-typed view by selecting the Atlassian.Jira class as Model class.

image

Click Add and the view is created.

If you hit F5 now, your browser should open up and you get already the overview screen for all issues returned from the filter you have selected.

In 10 minutes I’ve created a working (but ugly) web application that can fetch all the tickets I wanted to show to the customer. Of course your view will need some tweaking to show the values of the issues you want to be shown.

Adding a new issue

Adding a new issue to JIRA is as simply. (You can check the complete code on Github). I give you a (very) short overview.

Create 2 new methods Create in the HomeController. The first one just returned the view, the second one add the HttpPost attribute and this will receive an Atlassion.Issue object with all the values. Pushing this to JIRA is as simple to create a new issue object from the jira object and fill up the values. Hit SaveChanges on the jira object and your issue is created.

On thing I had a problem with is the projetc name – key difference in the jira.CreateIssue() method. I first tried with the project name but I got some HTML 500 error returning. Although for fetching issues this worked fine but for creating issues you apparently have to gibe the project key instead of the project name.

Look and feel

Ok, we have a working application but the look and feel isn’t that, certainly not enough to send to an end user. I didn’t wanted to spend to much time on the look and feel and decided to use the Twitter Bootstrap.

Don’t start downloading the package from the Twitter Bootstrap website. Instead use the nuget package manager again. There is a Bootstrap for MVC 4 package that will add all necessary items to your solution.

Open up the Package Manager Console again and run the following command:

Add bootstrap to the bundles

To add the bootstrap files to your application we’ve to alter the style and script bundles that are in use. Open up the BundleConfig.cs class in the App_Start folder. There we can add the necessary files to the bundles.

Online 28 I changed the the Content/css bundle to include the bootstrap css instead of the default Site.Css. On line 21 I added a script bundle to include the bootstrap.js file.

Because I added a script bundle we’ll have to add this bundle in the _ Layout.cshtml view.

Just underneath the rendering of the jQuery bundle add the rendering of the bootstrap bundle. (at the bottom of the view.

Result

I was able to create an new interface for our client to report bugs in just an hour of two. (the above only took 30 min but I’ve added some extra logic to send emails and stuff). Off course it’s not correct to add all business logic in your controllers and to hard code some strings and stuff. For this small application it’s more then enough. Underneath the screenshots of the 2 pages (in Dutch).

image

image

Source code

You can find this project on Github, feel free to fork, comment, …

One note, to avoid adding my personal credentials to the project I’ve created an xml file that holds the credentials in the App_Data folder. When creating the Jira object I fetch the values from this file. For obvious reasons I added this file to the .gitignore so it wouldn’t be pushed to Github. The structure of the file: