Skip navigation
Death Valley cast in a blue light sunrise in background

Build and Deploy a Website on Windows Azure Using ASP.NET MVC 3 and Razor

Develop an Azure cloud-based website using MVC 3, Razor, and SQL Azure

Last year, I volunteered to be the lead organizer for TechGate Conference 2011 in Reston, Virginia. Two of my first concerns were about the conference website. What technology should I choose to build the website, and where should I deploy the site? When planning for a conference, you have to deal with some unknowns: No one can predict how many people will register for the conference or when they will register for it. So the conference website must have high availability from site launch up to the conference completion. Another important requirement is that the site content must be easy to change, because typically there will be last-minute changes of speakers and session contents. We have to provide attendees with the latest information as we have it. For more information on Razor, see "Exploring the Razor Syntax in ASP.NET MVC 3" and "Working with the ASP.NET MVC 3 Razor View Engine."

After some consideration, I decided to use ASP.NET MVC 3 with the Razor view engine and deploy the site to the Windows Azure cloud platform, using SQL Azure for the back-end database. These decisions turned out to be a great choice for the conference registration website. Overall, I was really pleased with these exciting technologies: MVC 3 Razor and SQL Azure were easy to work with, and it didn't take me long to be able to use them productively. Another advantage to Azure is elasticity -- if necessary, we could easily scale our website up to multiple roles if demand got high enough. The TechGate Conference 2011 website was up and running in production from mid-May to mid-September 2011. The site experienced no outages of any kind during the conference registration period or the conference itself. In this article, I will discuss some parts of this project and a few lessons I learned in the process of developing and deploying the conference website.

Developing an MVC 3 Solution for Azure

The first step in developing an MVC 3 solution for Windows Azure is to make sure that you have all the necessary components ready, by installing the Windows Azure SDK and Windows Azure Tools for Microsoft Visual Studio, if you have not already done so. The Windows Azure SDK for .NET comes as an executable program, which you can download from the .NET Developer Center. (For more information about the Windows Azure Tools and other topics discussed in this article, see the articles list at the end of this article.) Once the Azure SDK and Tools are successfully installed, you are good to go. One of the nice features of the Azure Tools is the Windows Azure Storage Emulator, which is a local Windows Azure emulator that you can use to build and test your application before deploying it. Note that in order to run the Azure emulator, you must run Visual Studio as an administrator.

With Visual Studio fired up, in the New Project dialog box you'll find Cloud in the list of installed templates. Select the Cloud project template, then take the option to create a Windows Azure project.

Once the Windows Azure project is created, you'll need to choose one of the following roles listed on the New Windows Azure Project dialog box: ASP.NET Web Role, ASP.NET MVC 3 Web Role, ASP.NET MVC 2 Web Role, WCF Service Web Role, Worker Role, or Silverlight Business Application. A role in Windows Azure represents the type of application you would like to run inside Windows Azure. A Worker role is similar to a Windows service that runs background tasks. For our project, we need to select ASP.NET MVC 3 Web Role. You can rename the web role by right-clicking the web role name; for our project, I named the role ConferenceWebRole.

After you choose the role and click OK, Visual Studio will create the necessary files and folders for your Windows Azure project. Once the project is created, you'll see in Solution Explorer that our solution includes the MVC 3 project as a role, as shown in Figure 1.

Figure 1: Solution Explorer showing the Azure project's web role
Figure 1: Solution Explorer showing the Azure project's web role

Our solution also includes configuration files (.cscfg file extension) and a service definition file (.csdef file extension). The MVC 3 web role is structured as you would expect, with models, views, and controllers.

Without making changes to your project, you can try to run the MVC 3 project by pressing F5 or selecting Debug, Start Debug. You will then see a pop-up window showing the Windows Azure Debugging Environment getting started. This process initializes your local Azure emulator and will run your application in the emulator.

Once the Azure emulator is ready, you should be able to see the sample MVC 3 application running. For our conference website, I customized the tabs with the labels Home, Sessions, Speakers, Register, Travel, and Contact, as shown in Figure 2.

Figure 2: Conference website
Figure 2: Conference website

The Home, Travel, and Contact pages contain static information about the conference, so creating each of these pages was easily accomplished by creating a corresponding view to display the information. In the next section, we'll look at the site's data structure and discuss creation of the Sessions, Speakers, and Register pages, all of which are database-driven.

SQL Azure Database and the Data Model

Our conference site used SQL Azure as the back-end database. Why did I choose SQL Azure? First, I like the fact that the SQL Azure database is replicated three times on different servers in the same data center. This means that the database has high availability and redundancy is already built in. The conference data is vital for a successful event -- we can't afford to lose our database before the conference starts. Second, SQL Azure is easy to use. You can manage the database inside the SQL Azure management portal, issue familiar T-SQL commands from SQL Server Management Studio (I used version 2008 R2), or simply use ADO.NET.

Having chosen our website's database, the last thing I needed to do was to choose the right database size. SQL Azure is available in two editions: the Web Edition, which is available in two sizes, 1GB and 5GB, and the Business Edition, which is available in sizes ranging from 10GB to 150GB in 10GB increments. For our conference, we chose the Web Edition with 1GB.

After creating the database instance, there are two action items we need to consider. First, we need to add a firewall rule to allow our computer to access our SQL Azure database and another firewall rule to allow the Windows Azure web application to access the SQL Azure database. Second, we need to be sure to note our server name, the database name, and our login credentials. We'll need this information to connect to our SQL Azure database later.

A successful conference depends on motivated attendees, knowledgeable speakers, and well-organized sessions. So I needed to build the data model to include these entities. Having these tables in the database, as shown in Figure 3, made data updates easy, enabling the website to stay current without our having to redeploy the entire site.

Figure 3: Managing SQL Azure database tables in the management portal
Figure 3: Managing SQL Azure database tables in the management portal

Once the database and tables are created, we can easily add the ADO.NET Entity Data Model into our MVC 3 web solution in Visual Studio 2010. I found it easy and productive to use Entity Framework with our SQL Azure database. The logical place to add our Entity Data Model is in the Models folder. We just simply add a new item by clicking that folder. When the dialog box is displayed, choose ADO.NET Entity Data Model, as shown in Figure 4.

Figure 4: Adding the Entity Data Model
Figure 4: Adding the Entity Data Model

After clicking the Add button, the Entity Data Model Wizard is started; this wizard helps us to complete the action of adding our model. The next screen is where you choose the model content -- either from a database or by creating an empty model. Because our database is on SQL Azure, we choose to create our model from the database and provide connection information for the database. Once the Entity Data Model has been created, the tables from our database are represented in the model, as shown in Figure 5.

Figure 5: Entity Data Model for the Azure project
Figure 5: Entity Data Model for the Azure project

An advantage of MVC applications is that they are easy to test. To make our conference website easy to maintain and more testable, I used the Repository pattern. There are some benefits to using this pattern. Primarily, the repository class helps us to group all the data-querying activities and logic in one place, which reduces the amount of data-access implementation detail needed elsewhere in the application. If we need to change how we query our data or point to a different data source, the Repository pattern helps make that transition process easier. For the conference site, I added a repository class into our Models folder by selecting Add new item and then choosing a code class to add, as shown in Figure 6.

Figure 6: Repository class
Figure 6: Repository class

Figure 7 shows the code for the repository class.

public class TechGateRepository
    {
    private TechGateEntities entities = new TechGateEntities();

    public IQueryable FindAllMeetings()
    {
        return entities.Meetings.OrderBy(m => m.Title);
    }

    public Meeting GetMeeting(int id)
    {
        return entities.Meetings.FirstOrDefault(m => m.MeetingID == id);
    }

    public IQueryable FindAllSpeakers()
    {
        return entities.Speakers.Where(sp => sp.Display > 0).OrderBy(sp => sp.SpeakerID);
    }

    public Speaker GetSpeaker(int id)
    {
        return entities.Speakers.FirstOrDefault(s => s.SpeakerID == id);
    }

    public void Add(Attendee attendee)
    {
        entities.Attendees.AddObject(attendee);
    }

    public void Save()
    {
        entities.SaveChanges();
    }

}

With our repository in place, we can now create the site's data-driven pages -- for example, a page with a list of the conference speakers. Let's start with our controller. In the Controller folder, I created a new controller class named ConferenceController.cs with the intention that this controller will manage the relationship between model and view. The section of the controller code shown in Figure 8 displays a list of speakers on the view.

    public class ConferenceController : Controller
    {
    TechGateRepository repository = new TechGateRepository();

    public ActionResult Speakers()
    {
        var speakers = repository.FindAllSpeakers().ToList();
        return View("Speakers", speakers);
    }

}

The last thing we need to do is create the view to display the speakers. We can either create a view by adding a new item to the View folder in our project, or we can create a view by clicking the word View inside the ActionResult for Speakers. The code that creates the view to display the speakers, shown in Figure 9, is written using Razor syntax and is quite simple. Finally, after the view is created, when we run the application again the list of conference speakers is displayed.

@model IEnumerable

@{ ViewBag.Title = "Speakers";}

Speakers

@foreach (var item in Model) {

@Html.DisplayFor(modelItem => item.Name)

@Html.DisplayFor(modelItem => item.Name)
@Html.DisplayFor(modelItem => item.Bio)

}

Speakers

The examples we've just looked at show the process of building the conference speaker page using model, view, and controller and also demonstrate that the Razor view engine is easy to use. Now we'll move on to the next step, which is to build the slightly more complex attendee registration page.

Validation

In building the attendee registration page, a page that allows people to enter data, we need to additionally consider how to implement data validation and security as well as how to save the entered data. Here I'll focus on how our app handles data validation.

ASP.NET MVC 3 and MVC 2 include a useful feature called Data Annotation validation attributes. Data Annotation attributes include a System.ComponentModel.DataAnnotations namespace and allow you to specify various validation requirements, such as value range, required field, regular expressions, and string length. In our Model folder, I created an attendee partial class with attendee data validation. As you can see from the code in Figure 10, we made First Name a required field with a string length of 50 characters. For the Email field, we implemented regular expressions to ensure that the email format is valid.

[MetadataType(typeof(Attendee_Validation))]
    public partial class Attendee
    {
    }

public class Attendee_Validation
    {
    [Required(ErrorMessage = "First Name is required")]
    [StringLength(50, ErrorMessage= "First Name may not be longer than 50 characters")]
    public string FirstName { get; set; }

    [Required(ErrorMessage = "Last Name is required")]
    [StringLength(50, ErrorMessage = "Last Name may not be longer than 50 characters")]
    public string LastName { get; set; }

    [StringLength(125, ErrorMessage = "Title may not be longer than 125 characters")]
    public string Title { get; set; }

    [StringLength(150, ErrorMessage = "Company may not be longer than 150 characters")]
    public string Company { get; set; }

    [Required(ErrorMessage = "Email is required")]
    [RegularExpression("^[a-z0-9_\\+-]+(\\.[a-z0-9_\\+-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*\\.([a-z]{2,4})$", ErrorMessage = "Not a valid email")]
    [StringLength(150, ErrorMessage = "Email may not be longer than 150 characters")]
    public string Email { get; set; }

    [StringLength(50, ErrorMessage = "Phone may not be longer than 50 characters")]
    public string Phone { get; set; }

    public bool OptIn { get; set; }

}

To process the attendee registration data, we use an ActionResult class to register an attendee after an HTTP POST action occurs, as shown in Figure 11. Before we save our data, we check and make sure our model data is valid; if so, the data is saved. You might have noticed the email-sending code in this section -- I'll discuss this code next.

[HttpPost]
    public ActionResult Register(Attendee attendee)
    {
        if (ModelState.IsValid)
        {
        string emailSent = EmailHelper.SendEmail(attendee.FirstName, attendee.Email);
        attendee.EmailSent = emailSent;

        /// Add to the repository and save the record
        repository.Add(attendee);
        repository.Save();

        return RedirectToAction("Thankyou");
        }
        return View();
    }

Sending Email

A basic requirement of any conference-registration system is to send a confirmation email message to an attendee who has registered for the conference. Unfortunately, you cannot send email directly from the Windows Azure platform because your Azure cloud app has no dedicated IP address. This is a security measure to prevent Windows Azure data center servers from being targeted by prospective spammers, which could result in Azure data center IP addresses being added to spam blacklists. As an alternative to sending email from Azure, you can use a third-party email-delivery service such as SendGrid, the service that I selected for our conference app, to send email messages from an Azure web app.

When using an email-delivery service, your first task is to set up an account with the service. Once you've set up your account, you should be able to see the connection properties that you'll need to include in the application code that handles the sending of email. In our MVC 3 application, I simply created an email helper class to handle sending the email notifications, as shown in Figure 12, which is a simplified version of the actual code that sends a conference attendee an email confirmation upon completion of registration.

    public static string SendEmail(string FirstName, string Email)
    {
        string result = "Email sent";
        try
        {
        // To
        MailMessage mailMsg = new MailMessage();
        mailMsg.To.Add(Email);

        // From
        MailAddress mailAddress = new MailAddress(RoleEnvironment.GetConfigurationSettingValue("EmailAddress"));
        mailMsg.From = mailAddress;

        // Subject and Body
        mailMsg.Subject = "TechGate Conference Registration Confirmation";
        mailMsg.Body = "Dear " + FirstName + ":

Thank you for register TechGate Conference...."; mailMsg.IsBodyHtml = true; // Init SmtpClient and send SmtpClient smtpClient = new SmtpClient(RoleEnvironment.GetConfigurationSettingValue("SmtpServer"), int.Parse(RoleEnvironment.GetConfigurationSettingValue("SmtpPort"))); System.Net.NetworkCredential credentials = new System.Net.NetworkCredential(RoleEnvironment.GetConfigurationSettingValue("SmtpUsername"), RoleEnvironment.GetConfigurationSettingValue("SmtpPassword")); smtpClient.Credentials = credentials; smtpClient.Send(mailMsg); } catch (Exception ex) { result = ex.Message.ToString(); } return result; }

Deploying the App

After running our finished app on the Azure Emulator and making sure we're satisfied with it, the next step is to deploy the app to the Windows Azure platform. There are three popular deployment methods for Windows Azure: using Windows Azure Platform Management Portal, using Windows PowerShell, and using Visual Studio to publish an application to Azure. For the sake of brevity, in our example I will use Windows Azure Platform Management Portal to deploy our conference application. For detailed instructions on how to deploy a web app to Azure, see "How to Migrate a Web Application to Windows Azure and SQL Azure" and the articles listed at the end of this article.

Once you've created your Windows Azure account, you can log into the Windows Azure Platform Management Portal. Here, you can either deploy a new application or upgrade an existing application. You can create a production instance directly by choosing the New Production Deployment option or deploy your new application on staging first, via the New Staging Deployment option. Once the application is working well in staging, you can simply do a virtual IP (VIP) swap to switch the staging instance with the production instance. (For more information about staging, see "Manage Staging Deployments in Microsoft Windows Azure.")

Before we deploy to Windows Azure, we need to package our application. Windows Azure requires two files in a package: the solution package (the binary files that contains our entire application) and the configuration files (where our configuration settings are). To package the application, in Visual Studio Solution Explorer right-click on the Azure solution. You should see a Package option and Publish option; choose Package.

Next, you'll see the Package Windows Azure Application dialog box, shown in Figure 13.

Figure 13: Package Windows Azure Application dialog box
Figure 13: Package Windows Azure Application dialog box

If you accept the default settings, your package and configuration files will be packaged under a subdirectory named something like app.publish in the bin directory. You can use these files to publish to Windows Azure.

Once the packaging process is completed, you should see Windows Explorer open with your packaged files. (I usually copy the directory path to use later.) When you click any of the previously mentioned deployment options in the Windows Azure Platform Management Portal, the deployment dialog box asks you to enter a deployment name and provide the names of your solution package file and configuration file, as shown in Figure 14.

Figure 14: Deployment dialog box
Figure 14: Deployment dialog box

Once you've finished entering this information and clicked OK, Windows Azure will start working on creating your application instance. Soon you will be able to see your application running on Windows Azure.

Final Thoughts

Since last year's conference, ASP.NET MVC 4 -- now in beta -- is gaining my attention, with its modern styling and support for various popular mobile devices and web browsers. With more and more users using mobile devices to browse websites, it is necessary to allow users to use the website effectively on their devices. I'm looking forward to exploring MVC 4 and using it in upcoming website development projects.

Working with MVC 3, Razor, Windows Azure, and SQL Azure was an exciting and rewarding experience. I heard from some conference attendees who liked the fact that our conference had many cloud-computing related sessions and that the conference website is running in the cloud. If you have time, I encourage you to start building your next project using these technologies. Microsoft is adding new features continually -- there's never a dull moment!

I'll leave you with one reminder: Be sure to familiarize yourself with the Windows Azure billing terms. I made a mistake myself and ended up having to pay for an instance that stopped but was not removed. Once you have your first application successfully running on Windows Azure, you will gain confidence and knowledge of how all the pieces of an Azure web app fit together.

Andy Zhang is the leader of the Capital Area Cloud Computing User Group. He has more than 11 years of experience in software engineering. Recently, he has delivered numerous presentations on cloud computing and published articles on cloud security.

Learn more about Azure

Windows Azure SDK Tools:

SQL Azure:

Deploying an Application on Windows Azure:

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish