Deploy an ASP.NET MVC 5 mobile web app in Azure App Service

17 min to read Contributors
  • Cephas Lin
  • Kim Whitlatch
  • Tyson Nevil
  • Tom Dykstra
  • Rick Anderson

This tutorial will teach you the basics of how to build an ASP.NET MVC 5 web app that is mobile-friendly and deploy it to Azure App Service. For this tutorial, you need Visual Studio Express 2013 for Web or the professional edition of Visual Studio if you already have that. You can use Visual Studio 2015 but the screen shots will be different and you must use the ASP.NET 4.x templates.

Note

To complete this tutorial, you need an Azure account. You can activate your Visual Studio subscriber benefits or sign up for a free trial.

What You'll Build

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 ASP.NET sessions in the completed application, as seen in the browser emulator in Internet Explorer 11 F12 developer tools.

You can use the Internet Explorer 11 F12 developer tools and the Fiddler tool to help debug your application.

Skills You'll Learn

Here's what you'll learn:

  • How to use Visual Studio 2013 to publish your web application directly to a web app in Azure App Service.
  • How the ASP.NET MVC 5 templates use the CSS Bootstrap framework to improve display on mobile devices
  • How to create mobile-specific views to target specific mobile browsers, such as the iPhone and Android
  • How to create responsive views (views that respond to different browsers across devices)

Set up the development environment

Set up your development environment by installing the Azure SDK for .NET 2.5.1 or later.

  1. To install the Azure SDK for .NET, click the link below. If you don't have Visual Studio 2013 installed yet, it will be installed by the link. This tutorial requires Visual Studio 2013. Azure SDK for Visual Studio 2013
  2. In the Web Platform Installer window, click Install and proceed with the installation.

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

Visual Studio projects with C# source code are available to accompany this topic:

Deploy the starter project to an Azure web app

  1. Download the conference-listing application starter project.
  2. Then in Windows Explorer, right-click the downloaded ZIP file and choose Properties.
  3. In the 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.)
  4. Right-click the ZIP file and select Extract All to unzip the file.
  5. In Visual Studio, open the C#\Mvc5Mobile.sln file.
  6. In Solution Explorer, right-click the project and click Publish.

  7. In Publish Web, click Microsoft Azure App Service.

  8. If you haven't already logged into Azure, click Add an account.

  9. Follow the prompts to log into your Azure account.
  10. The App Service dialog should now show you as signed in. Click New.

  11. In the Web App Name field, specify a unique app name prefix. Your fully-qualified web app name will be <prefix>.azurewebsites.net. Also, select or specify a new resource group name in Resource group. Then, click New to create a new App Service plan.

  12. Configure the new App Service plan and click OK.

  13. Back in the Create App Service dialog, click Create.

  14. After the Azure resources are created, the Publish Web dialog will be filled with the settings for your new app. Click Publish.

    Once Visual Studio finishes publishing the starter project to the Azure web app, the desktop browser opens to display the live web app.

  15. Start your mobile browser emulator, copy the URL for the conference application (.azurewebsites.net) into the emulator, and then click the top-right button and select Browse by tag. If you are using Internet Explorer 11 as the default browser, you just need to type F12, then Ctrl+8, and then change the browser profile to Windows Phone. The image below shows the AllTags view in portrait mode (from choosing Browse by tag).

Tip

While you can debug your MVC 5 application from within Visual Studio, you can publish your web app to Azure again to verify the live web app directly from your mobile browser or a browser emulator.

The display is very readable on a mobile device. You can also already see some of the visual effects applied by the Bootstrap CSS framework. Click the ASP.NET link.

The ASP.NET tag view is zoom-fitted to the screen, which Bootstrap does for you automatically. However, you can improve this view to better suit the mobile browser. For example, the Date column is difficult to read. Later in the tutorial you'll change the AllTags view to make it mobile-friendly.

Bootstrap CSS Framework

New in the MVC 5 template is built-in Bootstrap support. You have already seen how it immediately improves the different views in your application. For example, the navigation bar at the top is automatically collapsible when the browser width is smaller. On the desktop browser, try resizing the browser window and see how the navigation bar changes its look and feel. This is the responsive web design that is built into Bootstrap.

To see how the Web app would look without Bootstrap, open App_Start\BundleConfig.cs and comment out the lines that contain bootstrap.js and bootstrap.css. The following code shows the last two statements of the RegisterBundles method after the change:

 bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
          //"~/Scripts/bootstrap.js",
          "~/Scripts/respond.js"));

bundles.Add(new StyleBundle("~/Content/css").Include(
          //"~/Content/bootstrap.css",
          "~/Content/site.css"));

Press Ctrl+F5 to run the application.

Observe that the collapsible navigation bar is now just an ordinary unordered list. Click Browse by tag again, then click ASP.NET. In the mobile emulator view, you can see now that it is no longer zoom-fitted to the screen, and you must scroll sideways in order to see the right side of the table.

Undo your changes and refresh the mobile browser to verify that the mobile-friendly display has been restored.

Bootstrap is not specific to ASP.NET MVC 5, and you can take advantage of these features in any web application. But it is now built into the ASP.NET MVC 5 project template, so that your MVC 5 Web application can take advantage of Bootstrap by default.

For more information about Bootstrap, go to the Bootstrap site.

In the next section you'll see how to provide mobile-browser specific views.

Override the Views, Layouts, and Partial Views

You can 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, you can copy Views\Home\Index.cshtml to Views\Home\Index.Mobile.cshtml.

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

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

In each Html.ActionLink call for the navigation bar, remove "Browse by" in each link ActionLink. The following code shows the completed <ul class="nav navbar-nav"> tag of the mobile layout file.

<ul class="nav navbar-nav">
    <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>

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 (the title from _Layout.Mobile.cshtml and the title from AllTags.Mobile.cshtml).

In contrast, the desktop display has not changed (with titles from _Layout.cshtml and AllTags.cshtml).

Create Browser-Specific Views

In addition to mobile-specific and desktop-specific views, you can create views for an individual browser. For example, you can create views that are specifically for the iPhone or the Android browser. In this section, you'll create a layout for the iPhone browser and an iPhone version of the AllTags view.

Open the Global.asax file and add the following code to the bottom of the Application_Start method.

DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("iPhone")
{
    ContextCondition = (context => context.GetOverriddenUserAgent().IndexOf
        ("iPhone", StringComparison.OrdinalIgnoreCase) >= 0)
});

This code defines a new display mode named "iPhone" that will be matched against each incoming request. If the incoming request matches the condition you defined (that is, if the user agent contains the string "iPhone"), ASP.NET MVC will look for views whose name contains the "iPhone" suffix.

Note

When adding mobile browser-specific display modes, such as for iPhone and Android, be sure to set the first argument to 0 (insert at the top of the list) to make sure that the browser-specific mode takes precedence over the mobile template (*.Mobile.cshtml). If the mobile template is at the top of the list instead, it will be selected over your intended display mode (the first match wins, and the mobile template matches all mobile browsers).

In the code, right-click DefaultDisplayMode, choose Resolve, and then choose using System.Web.WebPages;. This adds a reference to the System.Web.WebPages namespace, which is where the DisplayModeProvider and DefaultDisplayMode types are defined.

Alternatively, you can just manually add the following line to the using section of the file.

using System.Web.WebPages;

Save the changes. Copy the Views\Shared\_Layout.Mobile.cshtml file to Views\Shared\_Layout.iPhone.cshtml. Open the new file and then change the title from MVC5 Application (Mobile) to MVC5 Application (iPhone).

Copy the Views\Home\AllTags.Mobile.cshtml file to Views\Home\AllTags.iPhone.cshtml. In the new file, change the <h2> element from "Tags (M)" to "Tags (iPhone)".

Run the application. Run a mobile browser emulator, make sure its user agent is set to "iPhone", and browse to the AllTags view. If you are using the emulator in Internet Explorer 11 F12 developer tools, configure emulation to the following:

  • Browser profile = Windows Phone
  • User agent string = Custom
  • Custom string = Apple-iPhone5C1/1001.525

The following screenshot shows the AllTags view rendered in the emulator in Internet Explorer 11 F12 developer tools with the custom user agent string (this is an iPhone 5C user agent string).

In the mobile browser, select the Speakers link. Because there's not a mobile view (AllSpeakers.Mobile.cshtml), the default speakers view (AllSpeakers.cshtml) is rendered using the mobile layout view (_Layout.Mobile.cshtml). As shown below, the title MVC5 Application (Mobile) is defined in _Layout.Mobile.cshtml.

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";
    DisplayModeProvider.Instance.RequireConsistentDisplayMode = true;
}

When RequireConsistentDisplayMode is set to true, the mobile layout (_Layout.Mobile.cshtml) is used only for mobile views (i.e. when 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 (without the string "(Mobile)" in the navigational bar at the top).

You can disable consistent display mode in a specific 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";
    DisplayModeProvider.Instance.RequireConsistentDisplayMode = false;
}

In this section we've seen how to create mobile layouts and views and how to create layouts and views for specific devices such as the iPhone. However, the main advantage of the Bootstrap CSS framework is the responsive layout, which means that a single stylesheet can be applied across desktop, phone, and tablet browsers to create a consistent look and feel. In the next section you'll see how to leverage Bootstrap to create mobile-friendly views.

Improve the Speakers List

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 make the AllSpeakers view mobile-friendly, which displays large, easy-to-tap links and contains a search box to quickly find speakers.

You can use the Bootstrap linked list group styling to improve the Speakers view. In Views\Home\AllSpeakers.cshtml, replace the contents of the Razor file with the code below.

 @model IEnumerable<string>

@{
    ViewBag.Title = "All Speakers";
}

<h2>Speakers</h2>

<div class="list-group">
    @foreach (var speaker in Model)
    {
        @Html.ActionLink(speaker, "SessionsBySpeaker", new { speaker }, new { @class = "list-group-item" })
    }
</div>

The class="list-group" attribute in the <div> tag applies the Bootstrap list styling, and the class="input-group-item" attribute applies Bootstrap list item styling to each link.

Refresh the mobile browser. The updated view looks like this:

The Bootstrap linked list group styling makes the entire box for each link clickable, which is a much better user experience. Switch to the desktop view and observe the consistent look and feel.

Although the mobile browser view has improved, it's difficult to navigate the long list of speakers. Bootstrap doesn't provide a search filter functionality out-of-the-box, but you can add it with a few lines of code. You will first add a search box to the view, then hook up with the JavaScript code for the filter function. In Views\Home\AllSpeakers.cshtml, add a <form> tag just after the <h2> tag, as shown below:

@model IEnumerable<string>

@{
    ViewBag.Title = "All Speakers";
}

<h2>Speakers</h2>

<form class="input-group">
    <span class="input-group-addon"><span class="glyphicon glyphicon-search"></span></span>
    <input type="text" class="form-control" placeholder="Search speaker">
</form>
<br />
<div class="list-group">
    @foreach (var speaker in Model)
    {
        @Html.ActionLink(speaker, 
                         "SessionsBySpeaker", 
                         new { speaker }, 
                         new { @class = "list-group-item" })
    }
</div>

Notice that the <form> and <input> tags both have the Bootstrap styles applied to them. The <span> element adds a Bootstrap glyphicon to the search box.

In the Scripts folder, add a JavaScript file called filter.js. Open the file and paste the following code into it:

$(function () {

    // reset the search form when the page loads
    $("form").each(function () {
        this.reset();
    });

    // wire up the events to the <input> element for search/filter
    $("input").bind("keyup change", function () {
        var searchtxt = this.value.toLowerCase();
        var items = $(".list-group-item");

        // show all speakers that begin with the typed text and hide others
        for (var i = 0; i < items.length; i++) {
            var val = items[i].text.toLowerCase();
            val = val.substring(0, searchtxt.length);
            if (val == searchtxt) {
                $(items[i]).show();
            }
            else {
                $(items[i]).hide();
            }
        }
    });
});

You also need to include filter.js in your registered bundles. Open App_Start\BundleConfig.cs and change the first bundles. Change the first bundles.Add statement (for the jquery bundle) to include Scripts\filter.js, as follows:

 bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
            "~/Scripts/jquery-{version}.js",
            "~/Scripts/filter.js"));

The jquery bundle is already rendered by the default _Layout view. Later, you can utilize the same JavaScript code to apply the filter functionality to other list views.

Refresh the mobile browser and go to the AllSpeakers view. In the search box, type "sc". The speakers list should now be filtered according to your search string.

Improve the Tags List

Like the Speakers view, the Tags view is readable, but the links are small and difficult to tap on a mobile device. You can fix the Tags view the same way you fix the Speakers view, if you use the code changes described earlier, but with the following Html.ActionLink method syntax in Views\Home\AllTags.cshtml:

@Html.ActionLink(tag, 
                 "SessionsByTag", 
                 new { tag }, 
                 new { @class = "list-group-item" })

The refreshed desktop browser looks as follows:

And the refreshed mobile browser looks as follows:

Note

If you notice that the original list formatting is still there in the mobile browser and wonder what happened to your nice Bootstrap styling, this is an artifact of your earlier action to create mobile specific views. However, now that you are using the Bootstrap CSS framework to create a responsive web design, go head and remove these mobile-specific views and the mobile-specific layout views. Once you have done so, the refreshed mobile browser will show the Bootstrap styling.

Improve the Dates List

You can improve the Dates view like you improved the Speakers and Tags views if you use the code changes described earlier, but with the following Html.ActionLink method syntax in Views\Home\AllDates.cshtml:

@Html.ActionLink(date.ToString("ddd, MMM dd, h:mm tt"), 
                 "SessionsByDate", 
                 new { date }, 
                 new { @class = "list-group-item" })

You will get a refreshed mobile browser view like this:

You can further improve the Dates view by organizing the date-time values by date. This can be done with the Bootstrap panels styling. Replace the contents of the Views\Home\AllDates.cshtml file with the following code:

@model IEnumerable<DateTime>

@{
    ViewBag.Title = "All Dates";
}

<h2>Dates</h2>

@foreach (var dategroup in Model.GroupBy(x=>x.Date))
{
    <div class="panel panel-primary">
        <div class="panel-heading">
            @dategroup.Key.ToString("ddd, MMM dd")
        </div>
        <div class="panel-body list-group">
            @foreach (var date in dategroup)
            {
                @Html.ActionLink(date.ToString("h:mm tt"), 
                                 "SessionsByDate", 
                                 new { date }, 
                                 new { @class = "list-group-item" })
            }
        </div>
    </div>
}

This code creates a separate <div class="panel panel-primary"> tag for each distinct date in the list, and uses the linked list group for the respective links as before. Here's what the mobile browser looks like when this code runs:

Switch to the desktop browser. Again, note the consistent look.

Improve the SessionsTable View

In this section, you'll make the SessionsTable view more mobile-friendly. This change is more extensive the previous changes.

In the mobile browser, tap the Tag button, then enter asp in the search box.

Tap the ASP.NET link.

As you can see, the display is formatted as a table, which is currently designed to be viewed in the desktop browser. However, it's a little bit difficult to read on a mobile browser. To fix this, open Views\Home\SessionsTable.cshtml and then replace the contents of the file with the following code:

@model IEnumerable<Mvc5Mobile.Models.Session>

<h2>@ViewBag.Title</h2>

<div class="container">
    <div class="row">
        @foreach (var session in Model)
        {
            <div class="col-md-4">
                <div class="list-group">
                    @Html.ActionLink(session.Title, 
                                     "SessionByCode", 
                                     new { session.Code }, 
                                     new { @class="list-group-item active" })
                    <div class="list-group-item">
                        <div class="list-group-item-text">
                            @Html.Partial("_SpeakersLinks", session)
                        </div>
                        <div class="list-group-item-info">
                            @session.DateText
                        </div>
                        <div class="list-group-item-info small hidden-xs">
                            @Html.Partial("_TagsLinks", session)
                        </div>
                    </div>
                </div>
            </div>
        }
    </div>
</div>

The code does 3 things:

  • uses the Bootstrap custom linked list group to format the session information vertically, so that all this information is readable on a mobile browser (using classes such as list-group-item-text)
  • applies the grid system to the layout, so that the session items flow horizontally in the desktop browser and vertically in the mobile browser (using the col-md-4 class)
  • uses the responsive utilities to hide the session tags when viewed in the mobile browser (using the hidden-xs class)

You can also tap a title link to go to the respective session. The image below reflects the code changes.

The Bootstrap grid system that you applied automatically arranges the sessions vertically in the mobile browser. Also, notice that the tags are not shown. Switch to the desktop browser.

In the desktop browser, notice that the tags are now displayed. Also, you can see that the Bootstrap grid system you applied arranges the session items in two columns. If you enlarge the browser, you will see that the arrangement changes to three columns.

Improve the SessionByCode View

Finally, you'll fix the SessionByCode view to make it mobile-friendly.

In the mobile browser, tap the Tag button, then enter asp in the search box.

Tap the ASP.NET link. Sessions for the ASP.NET tag are displayed.

Choose the Building a Single Page Application with ASP.NET and AngularJS link.

The default desktop view is fine, but you can improve the look easily by using some Bootstrap GUI components.

Open Views\Home\SessionByCode.cshtml and replace the contents with the following markup:

@model Mvc5Mobile.Models.Session

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

<div class="panel panel-primary">
    <div class="panel-heading">
        Speakers
    </div>
    @foreach (var speaker in Model.Speakers)
    {
        @Html.ActionLink(speaker, 
                         "SessionsBySpeaker", 
                         new { speaker }, 
                         new { @class="panel-body" })
    }
</div>

<p>@Model.Abstract</p>

<div class="panel panel-primary">
    <div class="panel-heading">
        Tags
    </div>
    @foreach (var tag in Model.Tags)
    {
        @Html.ActionLink(tag, 
                         "SessionsByTag", 
                         new { tag }, 
                         new { @class = "panel-body" })
    }
</div>

The new markup uses Bootstrap panels styling to improve the mobile view.

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

Wrap Up and Review

This tutorial has shown you how to use ASP.NET MVC 5 to develop mobile-friendly Web applications. These include:

  • Deploy an ASP.NET MVC 5 application to an App Service web app
  • Use Bootstrap to create responsive web layout in your MVC 5 application
  • Override layout, views, and partial views, both globally and for an individual view
  • Control layout and partial override enforcement using the RequireConsistentDisplayMode property
  • Create views that target specific browsers, such as the iPhone browser
  • Apply Bootstrap styling in Razor code

See Also

What's changed