TFS Publishing with Azure Web Sites – Part 3

Summary

In this part we will add actual support for creating tasks in the application using LocalDB in our local development environment and separate Azure SQL databases on our Development and Production web sites. Being able to separate out the environments like this means developers can safely to changes locally without interfering with each other, deployments can be done to the Development site for testing purposes (without impacting the Production site) and once the application is deemed ready it can be deployed to the Production site.

Prerequisites

You will need to have these resources already configured:

It’s also helpful if you’ve followed all of the steps from parts one and two of this post where all the preparation for the steps in this part of the post.

Add Support for Adding To-Do Items

We’re going to add very basic support for creating to-do items and storing them in a SQL database. Using SQL Server for what we’re doing in this application is overkill, but we’re using it to demonstrate the basic technique.

Create the Data Project

We will be using Entity Framework (EF) to work with the to-do items. Start Visual Studio and open the ToDo solution from the Main branch. Right-click the solution node in the Solution Explorer window and select Add | <strong>New</strong> <strong>Project</strong> from the context menu.

In the Add New Project dialog, select to create a Class Library project, naming it <strong>ToDo</strong>.<strong>Data</strong>. The new project isn’t yet configured to use EF so go to Tools | <strong>Library</strong> <strong>Package</strong> <strong>Manager</strong> | <strong>Manage</strong> <strong>NuGet</strong> <strong>Packages</strong> <strong>for</strong> <strong>Solution</strong>. In the NuGet Packages dialog, select the All node under Installed packages and scroll down in the list until you see the EntityFramework package:

Figure 1 The NuGet Package Management dialog

Click the Manage button for the EntityFramework package. This displays a dialog that lets you add the EF package to the ToDo.Data project:

Figure 2 Adding the Entity Framework package to the ToDo.Data project

Click the OK button to add the package, wait while Visual Studio adds the package and then close the NuGet Packages dialog.

Add The ToDoItem Entity

Delete the Class1.cs file that Visual Studio added to the ToDo.Data project, right-click the ToDo.Data project and select Add | Class from the context menu. Name the file ToDoItem.cs. Replace the default contents of the new file with this code:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Publish.Data
{
    public class ToDoItem
    {
        [Key]
        public int Id { get; set; }

        public string Title { get; set; }

        public string Description { get; set; }

        public DateTime DueDate { get; set; }
    }
}

Next, add one more class to the ToDo.Data project and name it ToDoContext.cs and replace the contents of it with this code:

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Publish.Data
{
    public class ToDoContext : DbContext
    {
        public DbSet<span class="hljs-tag"><<span class="hljs-name">ToDoItem</span>></span> ToDoItems { get; set; }
    }
}

Finally, add a reference to ToDo.Data in the ToDo project by right-clicking the ToDo project and selecting Add Reference from the context menu. In the Reference Manager dialog, select Solution on the left and then check the ToDo.Data project and click OK:

Figure 3 Adding the reference to the ToDo.Data project

Configuring Entity Framework

The Entity Framework needs to be told which database to use. With Visual Studio 2012, LocalDB is a convenient option for local development use. In the ToDo project, open up web.config and in the section, copy the existing connection string and change the copy so the ` section looks like this:

<span class="hljs-tag"><<span class="hljs-name">connectionStrings</span>></span>
    <span class="hljs-tag"><<span class="hljs-name">add</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"DefaultConnection"</span> <span class="hljs-attr">connectionString</span>=<span class="hljs-string">"Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-ToDo-20130702090041;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-ToDo-20130702090041.mdf"</span> <span class="hljs-attr">providerName</span>=<span class="hljs-string">"System.Data.SqlClient"</span> /></span>
    <span class="hljs-tag"><<span class="hljs-name">add</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"ToDoContext"</span> <span class="hljs-attr">connectionString</span>=<span class="hljs-string">"Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-ToDo-Items;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-ToDo-Items.mdf"</span> <span class="hljs-attr">providerName</span>=<span class="hljs-string">"System.Data.SqlClient"</span> /></span>
<span class="hljs-tag"></<span class="hljs-name">connectionStrings</span>></span>

Add Support for Seeing the List of Tasks

In the ToDo project, open HomeController.cs and change the Index() method to look like this:

public ActionResult Index()
{
    ViewBag.Message = "Here you can see and create tasks.";

    List<span class="hljs-tag"><<span class="hljs-name">ToDoItem</span>></span> tasks;

    using ( var context = new ToDoContext() )
    {
        tasks = context.ToDoItems.ToList();
    }

    return View( tasks );
}

Next, open Index.cshtml in the Views | Home folder and change it to look like this:

@model IEnumerable<span class="hljs-tag"><<span class="hljs-name">ToDo.Data.ToDoItem</span>></span>

@{
    ViewBag.Title = "Home Page";
}
@section featured {
    <span class="hljs-tag"><<span class="hljs-name">section</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"featured"</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"content-wrapper"</span>></span>
            <span class="hljs-tag"><<span class="hljs-name">hgroup</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"title"</span>></span>
                <span class="hljs-tag"><<span class="hljs-name">h1</span>></span>@ViewBag.Title.<span class="hljs-tag"></<span class="hljs-name">h1</span>></span>
                <span class="hljs-tag"><<span class="hljs-name">h2</span>></span>@ViewBag.Message<span class="hljs-tag"></<span class="hljs-name">h2</span>></span>
            <span class="hljs-tag"></<span class="hljs-name">hgroup</span>></span>
            <span class="hljs-tag"><<span class="hljs-name">p</span>></span>
                Welcome to my To Do application
            <span class="hljs-tag"></<span class="hljs-name">p</span>></span>
        <span class="hljs-tag"></<span class="hljs-name">div</span>></span>
    <span class="hljs-tag"></<span class="hljs-name">section</span>></span>
}

<span class="hljs-tag"><<span class="hljs-name">h2</span>></span>Tasks<span class="hljs-tag"></<span class="hljs-name">h2</span>></span>

<span class="hljs-tag"><<span class="hljs-name">p</span>></span>
    @Html.ActionLink("Create Task", "Create")
<span class="hljs-tag"></<span class="hljs-name">p</span>></span>
<span class="hljs-tag"><<span class="hljs-name">table</span>></span>
    <span class="hljs-tag"><<span class="hljs-name">tr</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">th</span>></span>
            @Html.DisplayNameFor(model => model.Title)
        <span class="hljs-tag"></<span class="hljs-name">th</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">th</span>></span>
            @Html.DisplayNameFor(model => model.Description)
        <span class="hljs-tag"></<span class="hljs-name">th</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">th</span>></span>
            @Html.DisplayNameFor(model => model.DueDate)
        <span class="hljs-tag"></<span class="hljs-name">th</span>></span>
    <span class="hljs-tag"></<span class="hljs-name">tr</span>></span>

@foreach (var item in Model) {
    <span class="hljs-tag"><<span class="hljs-name">tr</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">td</span>></span>
            @Html.DisplayFor(modelItem => item.Title)
        <span class="hljs-tag"></<span class="hljs-name">td</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">td</span>></span>
            @Html.DisplayFor(modelItem => item.Description)
        <span class="hljs-tag"></<span class="hljs-name">td</span>></span>
        <span class="hljs-tag"><<span class="hljs-name">td</span>></span>
            @Html.DisplayFor(modelItem => item.DueDate)
        <span class="hljs-tag"></<span class="hljs-name">td</span>></span>
    <span class="hljs-tag"></<span class="hljs-name">tr</span>></span>
}

<span class="hljs-tag"></<span class="hljs-name">table</span>></span>

Add Support for Creating Tasks

Seeing the list of tasks isn’t very helpful unless we have a way to create tasks. Go back to `HomeController.cs and add these two methods:

public ActionResult Create()
{
    return View();
}

[HttpPost]
public ActionResult Create( ToDoItem item )
{
    using ( var context = new ToDoContext() )
    {
        context.ToDoItems.Add( item );
        context.SaveChanges();
    }

    return RedirectToAction( "Index" );
}

Next, right-click inside the parameter-less Create() method and select Add View from the context menu. In the Add View method, create a strongly-typed view for the ToDoItem class using the Create scaffolding template:

Figure 4 Adding the create view

Click Add to create the file Create.cshtml in the Views | Home folder.

Run and Test the Application Locally

We now have all the basic functionality in place for the application, press F5 to build and run the application and verify that you can create tasks and see them in the list of tasks on the home page:

Figure 5 The completed application

Configure Support for Development Web Site

At this point we have everything running locally, but in order to deploy the updated application to Azure we’ll need to switch to using SQL Server as LocalDB isn’t supported with Azure Web Sites.

Create the Development Database

Go to the Azure Management portal and create a new SQL Server database by clicking the plus sign in the lower left corner and then Data Services | SQL Database | Quick Create:

Figure 6 Creating a SQL Database for the development site

Since we’re creating the SQL Database for the development environment we’ll name it todo-demo-dev to make it obvious what the database is being used for. Make sure to take note of the login name and password you specify here as we’ll need them later. Click the check mark to create the database, this typically takes a few minutes.

Once the database has been created, go to the SQL Databases section of the Azure Management portal and click the name of the database to get to the dashboard tab. In the quick glance section, click the Show connection strings link to get the connection string we’ll need when deploying to the development web site:

Figure 7 The development database connection strings

Copy the ADO.NET connection string as this is the connection string we will be using in our application.

Configure Database Support for Deployments to the Development Site

The database connection string the application should use is defined in the web.config file associated with the application. The standard version of the web.config file in the project uses our local database so we need a way to change the web.config file when the application is deployed to the development environment. Visual Studio supports the concept of transforming the web.config file for different deployments that fits this need.

In Visual Studio, go to the Solution Explorer window and expand the ToDo | Properties | PublishProfiles folder where the publish profiles are located. Right-click the todo-demo-dev – Web Deploy.pubxml file and select Add Config Transform from the context menu:

Figure 8 Adding a config transform for the development web site

Visual Studio creates and opens the config transform file that includes an example for how to change a connection string. We’ll follow that example and add the connection string for the Azure SQL Database we created above:

<span class="php"><span class="hljs-meta"><?</span>xml version=<span class="hljs-string">"1.0"</span> encoding=<span class="hljs-string">"utf-8"</span><span class="hljs-meta">?></span></span>

<span class="hljs-comment"><!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 --></span>

<span class="hljs-tag"><<span class="hljs-name">configuration</span> <span class="hljs-attr">xmlns:xdt</span>=<span class="hljs-string">"http://schemas.microsoft.com/XML-Document-Transform"</span>></span>
  <span class="hljs-tag"><<span class="hljs-name">connectionStrings</span>></span>
    <span class="hljs-tag"><<span class="hljs-name">add</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"ToDoContext"</span>
      <span class="hljs-attr">connectionString</span>=<span class="hljs-string">"Server=tcp:myservername.database.windows.net,1433;Database=todo-demo-dev;User ID=todo-demo-dev@bsptsz1cfn;Password=mypassword;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;"</span>
  <span class="hljs-attr">xdt:Transform</span>=<span class="hljs-string">"SetAttributes"</span> <span class="hljs-attr">xdt:Locator</span>=<span class="hljs-string">"Match(name)"</span>/></span>
  <span class="hljs-tag"></<span class="hljs-name">connectionStrings</span>></span>
  <span class="hljs-tag"><<span class="hljs-name">system.web</span>></span>
    <span class="hljs-tag"><<span class="hljs-name">compilation</span> <span class="hljs-attr">xdt:Transform</span>=<span class="hljs-string">"RemoveAttributes(debug)"</span> /></span>
  <span class="hljs-tag"></<span class="hljs-name">system.web</span>></span>
<span class="hljs-tag"></<span class="hljs-name">configuration</span>></span>

Note that you will need to specify the name of your database server, user name and password you used when you created your database.

Check in the Changes and Test the Deployment

We’re now ready to check in all of our changes and trigger a build and deployment to the development web site:

Figure 9 Checking in the changes made in the Main branch and triggering the build and deployment

After checking in the changes, go to the Builds section of the Team Explorer window and see that the build has been triggered:

Figure 10 Build triggered by the check-in

Once the build completes you can open up the development web site and see that the application has been deployed and is running against the development database:

Figure 11 The application running in the development environment

Configure Support for Production Web Site

Once we get to the point where we’re getting ready to deploy version 2.0 of the application to the production site we’ll use the same steps as in part two of this post along with creating a production database:

  1. Create a Version 2.0 branch from the Main branch
  2. Create the production database in the Azure Management portal and copy the connection string
  3. Open the ToDo solution from the Version 2.0 branch and create a config transform for the production environment publish profile (todo-demo – Web Deploy.pubxml)
  4. Add the production database connection string to the new config transform and check it in
  5. Clone the Version 1.0 build definition and update it to build the solution from the Version 2.0 branch along with using the production web site publish profile from the Version 2.0 branch

Once these steps have been completed you can use the new build definition to build and deploy the application to the production environment.

CSG Pro

CSG Pro

Our data analytics consultants solve problems and ignite victories. We help you understand your data so you can make smarter business decisions. We build custom software applications that strengthen your process and your team.
SHARE THIS
Share on twitter
Share on facebook
Share on linkedin
Share on email
RELATED POSTS
Stay Connected

Subscribe to CSG Pro. We’ll supply your inbox with the latest blog posts, training videos, and upcoming events.

Search

Ready to wrangle your data?