Free trial

Deploy an ASP.NET MVC Mobile Web Application on Windows Azure Web Sites

By Rick Anderson Updated 15 April 2013.

This tutorial will teach you the basics of how to deploy a web application to to a Windows Azure web site. For the purposes of this tutorial we will work with mobile features in an ASP.NET MVC 4 web application. To perform the steps in this tutorial, you can use Microsoft Visual Studio 2012. You can also use Visual Studio Express 2012 or Visual Web Developer 2010 Express Service Pack 1 ("Visual Web Developer or VWD"), which are a free versions of Microsoft Visual Studio.

You will learn:

  • How the ASP.NET MVC 4 templates use the HTML5 viewport attribute and adaptive rendering to improve display on mobile devices.
  • How to create mobile-specific views.
  • How to create a view switcher that lets users toggle between a mobile view and a desktop view of the application.
  • How to deploy the web application to Windows Azure.

For this tutorial, you'll add mobile features to the simple conference-listing application that's provided in the starter project. The following screenshot shows the main page of the completed application as seen in the Windows 7 Phone Emulator.

MVC4 conference application main page.

Note

To complete this tutorial, you need a Windows Azure account that has the Windows Azure Web Sites feature enabled. You can create a free trial account and enable preview features in just a couple of minutes. For details, see Create a Windows Azure account and enable preview features.


Setting up the development environment

Set up your development environment by installing the Windows Azure SDK for the .NET Framework.

  1. To install the Windows Azure SDK for .NET, click the link below. If you don't have Visual Studio 2012 installed yet, it will be installed by the link. This tutorial requires Visual Studio 2012.
    Windows Azure SDK for Visual Studio 2012
  2. When you are prompted to run or save the installation executable, click Run.
  3. In the Web Platform Installer window, click Install and proceed with the installation.
    Web Platform Installer - Windows Azure SDK for .NET

You will also need a mobile browser emulator. Any of the following will work:

This tutorial shows code in C#. However, the starter project and completed project will be available in Visual Basic. Visual Studio projects with Visual Basic and C# source code are available to accompany this topic:

Steps in this tutorial

Create a web site in Windows Azure

Your Windows Azure Web Site will run in a shared hosting environment, which means it runs on virtual machines (VMs) that are shared with other Windows Azure clients. A shared hosting environment is a low-cost way to get started in the cloud. Later, if your web traffic increases, the application can scale to meet the need by running on dedicated VMs. If you need a more complex architecture, you can migrate to a Windows Azure cloud service. Cloud services run on dedicated VMs that you can configure according to your needs.

  1. Log on to the Windows Azure Management Portal. In the Management Portal, click New.

  2. Click Web Site, then click Quick Create.

  3. In the Create a New Web Site, enter a string in the URL box to use as the unique URL for your application.

    The complete URL will consist of what you enter here plus the suffix that you see below the text box. The illustration shows "MyMobileMVC4WebSite", but if someone has already taken that URL you will have to choose a different one. Select the REGION in which you are located.

  4. Click the check mark at the bottom of the box to indicate you're finished.

The Management Portal returns to the Web Sites page and the Status column shows that the site is being created. After a while (typically less than a minute) the Status column shows that the site was successfully created. In the navigation bar at the left, the number of sites you have in your account appears in the Web Sites icon, and the number of databases appears in the SQL Databases icon.

Setup the starter project.

  1. Download the conference-listing application starter project.

  2. Then in Windows Explorer, right-click the MvcMobileStarterBeta.zip file and choose Properties.

  3. In the MvcMobileRTMStarter.zip Properties dialog box, choose the Unblock button. (Unblocking prevents a security warning that occurs when you try to use a .zip file that you've downloaded from the web.)

    Properties dialog box.

  4. Right-click the MvcMobile.zip file and select Extract All to unzip the file.

  5. In Visual Web Developer or Visual Studio 2010, open the MvcMobile.sln file.

To run the starter project

  1. Press CTRL+F5 to run the application, which will display it in your desktop browser.
  2. Start your mobile browser emulator, copy the URL for the conference application into the emulator, and then click the Browse by tag link.

    • If you are using the Windows Phone Emulator, click in the URL bar and press the Pause key to get keyboard access. The image below shows the AllTags view (from choosing Browse by tag).

    Browse by tag page.

The display is very readable on a mobile device. Choose the ASP.NET link.

Browse sessions tagged as ASP.NET.

The ASP.NET tag view is very cluttered. For example, the Date column is very difficult to read. Later in the tutorial you'll create a version of the AllTags view that's specifically for mobile browsers and that will make the display readable.

Override the Views, Layouts, and Partial Views

In this section, you'll create a mobile-specific layout file.

A significant new feature in ASP.NET MVC 4 is a simple mechanism that lets you override any view (including layouts and partial views) for mobile browsers in general, for an individual mobile browser, or for any specific browser. To provide a mobile-specific view, you can copy a view file and add .Mobile to the file name. For example, to create a mobile Index view, copy Views\Home\Index.cshtml to Views\Home\Index.Mobile.cshtml.

To start, copy Views\Shared\_Layout.cshtml to Views\Shared\_Layout.Mobile.cshtml. Open _Layout.Mobile.cshtml and change the title from MVC4 Conference to Conference (Mobile).

In each Html.ActionLink call, remove "Browse by" in each link ActionLink. The following code shows the completed body section of the mobile layout file.

<body>
    <div class="page">
        <div id="header">
            <div id="logindisplay"></div>
            <div id="title">
                <h1> Conference (Mobile)</h1>
            </div>
            <div id="menucontainer">
                <ul id="menu">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("Date", "AllDates", "Home")</li>
                    <li>@Html.ActionLink("Speaker", "AllSpeakers", "Home")</li>
                    <li>@Html.ActionLink("Tag", "AllTags", "Home")</li>
                </ul>
            </div>
        </div>
        <div id="main">
            @RenderBody()
        </div>
        <div id="footer">
        </div>
    </div>
</body>

Copy the Views\Home\AllTags.cshtml file to Views\Home\AllTags.Mobile.cshtml. Open the new file and change the <h2> element from "Tags" to "Tags (M)":

<h2>Tags (M)</h2>

Browse to the tags page using a desktop browser and using mobile browser emulator. The mobile browser emulator shows the two changes you made.

Show changes to tags page

In contrast, the desktop display has not changed.

Show desktop tags view

Use jQuery Mobile to define the mobile broswer interface

In this section you'll install the jQuery.Mobile.MVC NuGet package, which installs jQuery Mobile and a view-switcher widget.

The jQuery Mobile library provides a user interface framework that works on all the major mobile browsers. jQuery Mobile applies progressive enhancement to mobile browsers that support CSS and JavaScript. Progressive enhancement allows all browsers to display the basic content of a web page, while allowing more powerful browsers and devices to have a richer display. The JavaScript and CSS files that are included with jQuery Mobile style many elements to fit mobile browsers without making any markup changes.

  1. Delete the Shared\_Layout.Mobile.cshtml file that you created earlier.

  2. Rename the Views\Home\AllTags.Mobile.cshtml to Views\Home\AllTags.Mobile.cshtml.hide (you will use this file again later.) Because the file no longer has a .cshtml extension, it will not be used by the ASP.NET MVC runtime to render the AllTags view.

  3. Install the jQuery.Mobile.MVC NuGet package by doing this:

    a. From the Tools menu, select Package Manager Console, and then select Library Package Manager.

    ![Library package manager][jquery1]

    b. In the Package Manager Console, enter Install-Package jQuery.Mobile.MVC -version 1.0.0

    ![Package manager console][jquery2]

The jQuery.Mobile.MVC NuGet package installs the following:

  • The App_Start\BundleMobileConfig.cs file, which is needed to reference the jQuery JavaScript and CSS files added. You must follow the instructions below and reference the mobile bundle defined in this file.
  • jQuery Mobile CSS files.
  • A ViewSwitcher controller widget (Controllers\ViewSwitcherController.cs).
  • jQuery Mobile JavaScript files.
  • A jQuery Mobile-styled layout file (Views\Shared_Layout.Mobile.cshtml).
  • A view-switcher partial view (MvcMobile\Views\Shared_ViewSwitcher.cshtml) that provides a link at the top of each page to switch from desktop view to mobile view and vice versa.
  • Several .png and .gif image files in the Content\images folder.

Open the Global.asax file and add the following code as the last line of the Application_Start method.

BundleMobileConfig.RegisterBundles(BundleTable.Bundles);

The following code shows the complete Global.asax file.

using System; 
using System.Web.Http; 
using System.Web.Mvc; 
using System.Web.Optimization; 
using System.Web.Routing; 
using System.Web.WebPages; 

namespace MvcMobile 
{ 

    public class MvcApplication : System.Web.HttpApplication 
    { 
        protected void Application_Start() 
        { 
            DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("iPhone") 
            { 
                ContextCondition = (context => context.GetOverriddenUserAgent().IndexOf 
                    ("iPhone", StringComparison.OrdinalIgnoreCase) >= 0) 
            }); 
            AreaRegistration.RegisterAllAreas(); 

            WebApiConfig.Register(GlobalConfiguration.Configuration); 
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
            RouteConfig.RegisterRoutes(RouteTable.Routes); 
            BundleConfig.RegisterBundles(BundleTable.Bundles); 
            BundleMobileConfig.RegisterBundles(BundleTable.Bundles); 
        } 
    } 
}

Open the MvcMobile\Views\Shared\_Layout.Mobile.cshtml file and add the following markup directly after the Html.Partial call:

<div data-role="header" align="center">
    @Html.ActionLink("Home", "Index", "Home")
    @Html.ActionLink("Date", "AllDates")
    @Html.ActionLink("Speaker", "AllSpeakers")
    @Html.ActionLink("Tag", "AllTags")
</div>

The complete body section looks like this:

<body>
    <div data-role="page" data-theme="a">
        @Html.Partial("_ViewSwitcher")
        <div data-role="header" align="center">
            @Html.ActionLink("Home", "Index", "Home")
            @Html.ActionLink("Date", "AllDates")
            @Html.ActionLink("Speaker", "AllSpeakers")
            @Html.ActionLink("Tag", "AllTags")
        </div>
        <div data-role="header">
            <h1>@ViewBag.Title</h1>
        </div>
        <div data-role="content">
            @RenderSection("featured", false)
            @RenderBody()
        </div>
    </div>
</body>

Build the application, and in your mobile browser emulator browse to the AllTags view. You see the following:

After install jquery through nuget.

Note

You can debug the mobile specific code by setting the user agent string for IE or Chrome to iPhone and then using the F-12 developer tools. If your mobile browser doesn't display the Home, Speaker, Tag, and Date links as buttons, the references to jQuery Mobile scripts and CSS files are probably not correct.

In addition to the style changes, you see Displaying mobile view and a link that lets you switch from mobile view to desktop view. Choose the Desktop view link, and the desktop view is displayed.

The desktop view doesn't provide a way to directly navigate back to the mobile view. You'll fix that now. Open the Views\Shared\_Layout.cshtml file. Just under the <body> element, add the following code, which renders the view-switcher widget:

@Html.Partial("_ViewSwitcher")

Here's the completed code:

<body>
    @Html.Partial("_ViewSwitcher")

    <div id="title">
        <h1> MVC4 Conference </h1>
    </div>

    @*Items removed for clarity.*@
</body>

Refresh the AllTags view is the mobile browser. You can now navigate between desktop and mobile views.

Navigate to mobile views.

Note

You can add the following code to the end of the Views\Shared\_ViewSwitcher.cshtml to help debug views when using a browser the user agent string set to a mobile device.

else 
    { 
         @:Not Mobile/Get 
    }

and adding the following heading to the Views\Shared\_Layout.cshtml file.


<h1>Non Mobile Layout MVC4 Conference</h1>

Browse to the AllTags page in a desktop browser. The view-switcher widget is not displayed in a desktop browser because it's added only to the mobile layout page. Later in the tutorial you'll see how you can add the view-switcher widget to the desktop view.

View desktop experience.

Improve the Speakers List

In the mobile browser and select the Speakers link. Because there's no mobile view(AllSpeakers.Mobile.cshtml), the default speakers display (AllSpeakers.cshtml) is rendered using the mobile layout view (_Layout.Mobile.cshtml).

View the mobile speakers list.

You can globally disable a default (non-mobile) view from rendering inside a mobile layout by setting RequireConsistentDisplayMode to true in the Views_ViewStart.cshtml file, like this:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    DisplayModes.RequireConsistentDisplayMode = true;
}

When RequireConsistentDisplayMode is set to true, the mobile layout (_Layout.Mobile.cshtml) is used only for mobile views. (That is, the view file is of the form ViewName.Mobile.cshtml.) You might want to set RequireConsistentDisplayMode to true if your mobile layout doesn't work well with your non-mobile views. The screenshot below shows how the Speakers page renders when RequireConsistentDisplayMode is set to true.

You can disable consistent display mode in a view by setting RequireConsistentDisplayMode to false in the view file. The following markup in the Views\Home\AllSpeakers.cshtml file sets RequireConsistentDisplayMode to false:

@model IEnumerable<string>
@{
    ViewBag.Title = "All speakers";
    DisplayModes.RequireConsistentDisplayMode = false;
}

Create a Mobile Speakers View

As you just saw, the Speakers view is readable, but the links are small and are difficult to tap on a mobile device. In this section, you'll create a mobile-specific Speakers view that looks like a modern mobile application — it displays large, easy-to-tap links and contains a search box to quickly find speakers.

  1. Copy AllSpeakers.cshtml to AllSpeakers.Mobile.cshtml. Open the AllSpeakers.Mobile.cshtml file and remove the <h2> heading element.
  2. In the <ul> tag, add the data-role attribute and set its value to listview. Like other data-* attributes, data-role="listview" makes the large list items easier to tap. This is what the completed markup looks like:

    @model IEnumerable<string>
    @{
        ViewBag.Title = "All speakers";
    }
    <ul data-role="listview">
        @foreach(var speaker in Model) {
            <li>@Html.ActionLink(speaker, "SessionsBySpeaker", new { speaker })</li>
        }
    </ul>
  3. Refresh the mobile browser. The updated view looks like this:

  4. In the <ul> tag, add the data-filter attribute and set it to true. The code below shows the ul markup.

    <ul data-role="listview" data-filter="true">

The following image shows the search filter box at the top of the page that results from the data-filter attribute.

As you type each letter in the search box, jQuery Mobile filters the displayed list as shown in the image below.

Improve the Tags List

Like the default Speakers view, the Tags view is readable, but the links are small and difficult to tap on a mobile device. In this section, you'll fix the Tags view the same way you fixed the Speakers view.

  1. Rename the Views\Home\AllTags.Mobile.cshtml.hide file to the Views\Home\AllTags.Mobile.cshtml. Open the renamed file and remove the <h2> element.

  2. Add the data-role and data-filter attributes to the <ul> tag, as shown here:

    <ul data-role="listview" data-filter="true">

    The image below shows the tags page filtering on the letter J.

Improve the Dates List

You can improve the Dates view like you improved the Speakers and Tags views, so that it's easier to use on a mobile device.

  1. Copy the Views\Home\AllDates.Mobile.cshtml file to Views\Home\AllDates.Mobile.cshtml.
  2. Open the new file and remove the <h2> element.
  3. Add data-role="listview" to the <ul> tag, like this:

    <ul data-role="listview">

The image below shows what the Date page looks like with the data-role attribute in place.

Replace the contents of the Views\Home\AllDates.Mobile.cshtml file with the following code:

@model IEnumerable<DateTime>
@{
    ViewBag.Title = "All dates";
    DateTime lastDay = default(DateTime);
}
<ul data-role="listview">
    @foreach(var date in Model) {
        if (date.Date != lastDay) {
            lastDay = date.Date;
            <li data-role="list-divider">@date.Date.ToString("ddd, MMM dd")</li>
        }
        <li>@Html.ActionLink(date.ToString("h:mm tt"), "SessionsByDate", new { date })</li>
    }
</ul>

This code groups all sessions by days. It creates a list divider for each new day, and it lists all the sessions for each day under a divider. Here's what it looks like when this code runs:

Improve the SessionsTable View

In this section, you'll create a mobile-specific view of sessions. The changes we make will be more extensive than in other views we have created.

In the mobile browser, tap the Speaker button, then enter Sc in the search box.

Tap the Scott Hanselman link.

As you can see, the display is difficult to read on a mobile browser. The date column is hard to read and the tags column is out of the view. To fix this, copy Views*Home\SessionsTable.cshtml* to Views\Home\SessionsTable.Mobile.cshtml, and then replace the contents of the file with the following code:

@using MvcMobile.Models
@model IEnumerable<Session>

<ul data-role="listview">
    @foreach(var session in Model) {
        <li>
            <a href="@Url.Action("SessionByCode", new { session.Code })">
                <h3>@session.Title</h3>
                <p><strong>@string.Join(", ", session.Speakers)</strong></p>
                <p>@session.DateText</p>
            </a>
        </li>
    }
</ul>

The code removes the room and tags columns, and formats the title, speaker, and date vertically, so that all this information is readable on a mobile browser. The image below reflects the code changes.

Improve the SessionByCode View

Finally, you'll create a mobile-specific view of the SessionByCode view. In the mobile browser, tap the Speaker button, then enter Sc in the search box.

Tap the Scott Hanselman link. Scott Hanselman's sessions are displayed.

Choose the An Overview of the MS Web Stack of Love link.

The default desktop view is fine, but you can improve it.

Copy the Views\Home\SessionByCode.cshtml to Views\Home\SessionByCode.Mobile.cshtml and replace the contents of the Views\Home\SessionByCode.Mobile.cshtml file with the following markup:

@model MvcMobile.Models.Session

@{
    ViewBag.Title = "Session details";
}
<h2>@Model.Title</h2>
<p>
    <strong>@Model.DateText</strong> in <strong>@Model.Room</strong>
</p>

<ul data-role="listview" data-inset="true">
    <li data-role="list-divider">Speakers</li>
    @foreach (var speaker in Model.Speakers) {
        <li>@Html.ActionLink(speaker, "SessionsBySpeaker", new { speaker })</li>
    }
</ul>

<p>@Model.Description</p>
<h4>Code: @Model.Code</h4>

<ul data-role="listview" data-inset="true">
    <li data-role="list-divider">Tags</li>
    @foreach (var tag in Model.Tags) {
        <li>@Html.ActionLink(tag, "SessionsByTag", new { tag })</li>
    }
</ul>

The new markup uses the data-role attribute to improve the layout of the view.

Refresh the mobile browser. The following image reflects the code changes that you just made:

Deploy the Application to the Windows Azure Web Site

  1. In Visual Studio, right-click the project in Solution Explorer and select Publish from the context menu.
    Publish in project context menu
    The Publish Web wizard opens.
  2. In the Profile tab of the Publish Web wizard, click Import.
    Import publish settings The Import Publish Profile dialog box appears.
  3. If you have not previously added your Windows Azure subscription in Visual Studio, perform the following steps. In these steps you add your subscription so that the drop-down list under Import from a Windows Azure web sitewill include your web site.
    1. In the Import Publish Profile dialog box, click Add Windows Azure subscription.
      add win az sub
    2. In the Import Windows Azure Subscriptions dialog box, click Download subscription file.
      download sub
    3. In your browser window, save the .publishsettings file.
      download pub file
      Security Note

      The .publishsettings file contains your credentials (unencoded) that are used to administer your Windows Azure subscriptions and services. The security best practice for this file is to store it temporarily outside your source directories (for example in the Libraries\Documents folder), and then delete it once the import has completed. A malicious user who gains access to the .publishsettings file can edit, create, and delete your Windows Azure services.

    4. In the Import Windows Azure Subscriptions dialog box, click Browse and navigate to the .publishsettings file.
      download sub
    5. Click Import.
      import
  4. In the Import Publish Profile dialog box, select Import from a Windows Azure web site, select your web site from the drop-down list, and then click OK.
    Import Publish Profile

  5. In the Connection tab, click Validate Connection to make sure that the settings are correct.
    Validate connection

  6. When the connection has been validated, a green check mark is shown next to the Validate Connection button.

    connection successful icon and Next button in Connection tab
  7. You can accept all of the default settings on this page. You are deploying a Release build configuration and you don't need to delete files at the destination server. The UsersContext (DefaultConnection) entry under Databases comes from the UsersContext:DbContext class which uses the DefaultConnection string.
    Click Next.


    connection successful icon and Next button in Connection tab

  8. In the Preview tab, click Start Preview.
    The tab displays a list of the files that will be copied to the server. Displaying the preview isn't required to publish the application but is a useful function to be aware of. In this case, you don't need to do anything with the list of files that is displayed. The next time you publish, only the files that have changed will be in the preview list.
    StartPreview button in the Preview tab
  9. Click Publish.
    Visual Studio begins the process of copying the files to the Windows Azure server. The Output window shows what deployment actions were taken and reports successful completion of the deployment.

  10. The default browser automatically opens to the URL of the deployed site. The application you created is now running in the cloud.

You can test your live web site using the phone emulator by browsing to the site URL in the mobile browser.