This tutorial describes the process of setting up a simple ASP.NET MVC Web Application with Entity Framework and Code First Migrations and a workflow for developing, testing, staging and deploying the application with full automation using GitHub, Jenkins and IIS.
First of all, make sure you have installed the following software:
Create a new repository in GitHub and clone it to your machine. Using your preferred Git client, add three branches – develop, test and production. You might add more, less or other ones depending on your branching strategy, but this will suffice for this example. For example, there may be multiple development, test and production branches, for example if you are maintaining and developing an older version of your software.
The develop branch is the common “snapshot” branch that developers merge their completed features or bug fixes into and it can be built on Jenkins. The test and production branches will be used to build your application for the corresponding environments and optionally publishing them automatically. Push all three branches to the remote GitHub repository.
(Optional) To prevent developers from merging untested code into test and production you can use the fork/pull request GitHub features. In that scenario, Jenkins will pull code from one GitHub account’s repository to which only certain developers and release managers have push access.
The drawback with this setup is that it requires developers to issue pull requests even when merging into develop. You could also create another repository where all developers has push access and pull develop from that repository.
Create and checkout a new branch called setup. Add a .gitignore file in the git root directory with the following rules and the ones in CSharp.gitignore.
Add .gitignore to index and commit.
In this part you can create a MVC Web Application, Intranet Application or Web API project. The examples will be a basic Web Application called MyApp. Feel free to commit changes in Git along the way.
Open Visual Studio and create a new MVC Web Application project. Make sure that the EntityFramework NuGet package is added. Open the Package Manager Console and run
Enable-PackageRestore or right-click your solution and click Enable NuGet Package Restore.
Create a model class Thing and a DbContext for your EF context. This is described in detail at Entity Framework Code First Migrations.
Open Web.config and locate the
<connectionStrings>...</connectionStrings> section. Add the following. Replace
SQLEXPRESS if you named your SQL Express instance to something else.
Add a default constructor to your DbContext class. The name in the constructor must be equal to the
name="..." attribute in the Web.config connection string. This explicitly tells the context to use the connection string you added in the previous step.
In the Package Manager Console, run
Enable-Migrations. This will scaffold a basic configuration under
AutomaticMigrationsEnabled = true in the constructor.
To use the configuration in your web application, add the following line to
Application_Start() in Global.asax.
Run Add-Migration in the Package Manager Console, enter a name (e.g. InitialMigration) and a DbMigration class is created. Use this method to create incremental migrations when you change persisted model classes. Read more on customizing migrations at MSDN’s Entity Framework Code First Migrations. Run
Update-Database to manually apply the migrations to your SQL Express database.
In this step you will create two publish profiles, one for each target environment, which will be used to publish the application from Jenkins once built and tested.
To be able to distinguish the environment in which your application is deployed, add the following to
<appSettings>...</appSettings> in your Web.config:
<add key="Environment" value="Development" />
Open Explorer, navigate to the web project’s root directory, create two copies of Web.Release.config and name them Web.Test.config and Web.Production.config. Go back to Visual Studio and toggle Show all files in the Solution Explorer. Select your two new files, right click and click Include In Project. You can now override properties in these new profiles. For example in Web.Test.config:
Right-click your web project and click Publish. Add a new profile and call it Test. Note that the name Test matches the Web.Test.config, which is a convention for transforms and profiles.
In the Connection tab, set Publish method to Web Deploy Package. Set Package location to
obj\Package\MyApp-Test.zip. This path is relative to the web project root and could be anything you like. Site/application can also be anything but must match the site name in IIS which you will setup later. Set it to MyApp.
Check Execute Code First Migrations [...]. If you don’t need any specific connection string for the deployment machine, uncheck Use this connection at runtime [...]. Also, the connection string can be set directly in IIS, which I think is a more clean solution.
Repeat these steps but call the configuration Production instead of Test.
By default, when you create a MVC Web Application, you get a test project which uses MSTest. To run these tests you must have Visual Studio (higher than Express) installed. This may work at your development machine but at the build server this can become quite clumsy. Instead, let’s use NUnit!
Add the NUnit and NUnit.Runners NuGet packages to your test project(s). If you have any MSTest cases, change the Attributes from the MSTest specific ones to NUnit Attributes (e.g.
If you have multiple projects in your solution (code libraries, web projects, test projects), or just want to customize your build, MSBuild is very handy.
NOTE! In this example MSBuild Extensions Pack is used. It’s possible to skip this and use the built in MSBuild tasks, but it can be convenient.
As this might become quite a large file, all details of how this works will not be covered in this example. To sum it up, the build.xml will contain a number of targets which aggregates the individual project targets. The following is the build.xml used to build the example project.