ASP.NET MVC 4 Mobile Features


Source : www.asp.net

This tutorial will teach you the basics of how to work with mobile features in an ASP.NET MVC 4 developer preview Web application. For this tutorial, you can use Microsoft Visual Web Developer 2010 Express Service Pack 1 (“Visual Web Developer”), which is a free version of Microsoft Visual Studio. Or you can use Visual Studio 2010 SP1 if you already have that.

Before you start, make sure you’ve installed the prerequisites listed below.

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:

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 tags page of the completed application as seen in the Windows 7 Phone Emulator (RC).

p1_Tags_CompletedProj

Skills You’ll Learn

Here’s what you’ll 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.

Getting Started

Download the conference-listing application for the starter project using the following link: Download. Then in Windows Explorer, right-click the MvcMobile.zip file and choose Properties. In the MvcMobile.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.)

p1_unBlock

Right-click the MvcMobile.zip file and select Extract All to unzip the file. In Visual Web Developer or Visual Studio 2010, open the MvcMobile.sln file.

Press CTRL+F5 to run the application, which will display it in your desktop browser. 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).

p1_browseTag

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

p1_tagged_ASPNET

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.

CSS Media Queries

CSS media queries are an extension to CSS for media types. They allow you to create rules that override the default CSS rules for specific browsers (user agents). A common rule for CSS that targets mobile browsers is defining the maximum screen size. The Content\Site.css file that’s created when you create a new ASP.NET MVC 4 Internet project contains the following media query:

@media only screen and (max-width: 850px) {

If the browser window is 850 pixels wide or less, it will use the CSS rules inside this media block. You can use CSS media queries like this to provide a better display of HTML content on small browsers (like mobile browsers) than the default CSS rules that are designed for the wider displays of desktop browsers.

The Viewport Meta Tag

Most mobile browsers define a virtual browser window width (the viewport) that’s much larger than the actual width of the mobile device. This allows mobile browsers to fit the entire web page inside the virtual display. Users can then zoom in on interesting content. However, if you set the viewport width to the actual device width, no zooming is required, because the content fits in the mobile browser.

The viewport <meta> tag in the ASP.NET MVC 4 layout file sets the viewport to the device width. The following line shows the viewport <meta> tag in the ASP.NET MVC 4 layout file.

 <meta name="viewport" content="width=device-width">

Examining the Effect of CSS Media Queries and the Viewport Meta Tag

Open the MvcMobile\Views\Shared\_Layout.cshtml file in the editor and comment out the viewport <meta> tag. The following markup shows the commented-out line.

@*<meta name="viewport" content="width=device-width">*@

Open the MvcMobile\Content\Site.css file in the editor and change the maximum width in the media query to zero pixels. This will prevent the CSS rules from being used in mobile browsers. The following line shows the modified media query:

@media only screen and (max-width: 0px) { ...

Save your changes and browse to the Conference application in a mobile browser emulator. The tiny text in the following image is the result of removing the viewport <meta> tag. With no viewport <meta> tag, the browser is zooming out to the default viewport width (850 pixels or wider for most mobile browsers.)

p1_noViewPort

Undo your changes — uncomment the viewport <meta> tag in the layout file and restore the media query to 850 pixels in the Site.css file. Save your changes and refresh the mobile browser to verify that the mobile-friendly display has been restored.

The viewport <meta> tag and the CSS media query are not specific to ASP.NET MVC 4, and you can take advantage of these features in any web application. But they are now built into the files that are generated when you create a new ASP.NET MVC 4 project.

For more information about the viewport <meta> tag, see A tale of two viewports — part two.

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

Overriding Views, Layouts, and Partial Views

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.

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 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.

p2m_layoutTags.mobile

In contrast, the desktop display has not changed.

p2_layoutTagsDesktop

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 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 Application_Start method.

DisplayModes.Modes.Insert(0, new DefaultDisplayMode("iPhone")
{
    ContextCondition = (ctx => ctx.Request.UserAgent.IndexOf(
        "iPhone", StringComparison.OrdinalIgnoreCase) >= 0)
});

Here’s the complete Application_Start method:

protected void Application_Start() {
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
    DisplayModes.Modes.Insert(0, new DefaultDisplayMode("iPhone")
    {
        ContextCondition = (ctx => ctx.Request.UserAgent.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.

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 DisplayModes and DefaultDisplayMode types are defined.

p2_resolve

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 MvcMobile\Views\Shared\_Layout.Mobile.cshtml file to MvcMobile\Views\Shared\_Layout.iPhone.cshtml. Open the new file and then change the h1 heading from Conference (Mobile) to Conference (iPhone).

Copy the MvcMobile\Views\Home\AllTags.Mobile.cshtml file to MvcMobile\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. The following screenshot shows the AllTags view rendered in the Safari browser.

p2_iphoneView

(For instructions on how to set the user agent string in an Safari browser to emulate an iPhone, see How to let Safari pretend it’s IE in David Alison’s blog.)

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. In the next section you’ll see how to leverage jQuery Mobile for more compelling mobile views.

Using jQuery Mobile

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.

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

To start, delete the Shared\_Layout.Mobile.cshtml and Shared\_Layout.iPhone.cshtml files that you created earlier.

Rename Views\Home\AllTags.Mobile.cshtml to Views\Home\AllTags.iPhone.cshtml.hide. Because the files no longer have a .cshtml extension, they won’t be used by the ASP.NET MVC runtime to render the AllTags view.

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

  1. From the Tools menu, select Package Manager Console, and then select Library Package Manager.p3_packageMgr
  2. In the Package Manager Console, enter Install-Package jQuery.Mobile.MVCp3_packageMgrConsole

Note If you get the following error:
The file C:\my_script.ps1 cannot be loaded. The execution of scripts is disabled on this system. Please see “Get-Help about_signing” for more details

See Scott Hanselman’s blog Signing PowerShell Scripts. You can run the following in a power shell script to allow signed scripts to run:

Set-ExecutionPolicy AllSigned

This command requires administrator privileges.  Changes to the execution policy are recognized immediately.

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

  • jQuery Mobile (jquery.mobile-1.0b3.js and the minified version jquery.mobile-1.0b3.min.js).
  • A jQuery Mobile-styled layout file (Views\Shared\_Layout.Mobile.cshtml).
  • A jQuery Mobile CSS file (jquery.mobile-1.0b3.css and the minified version jquery.mobile-1.0b3.min.css)
  • Several .png image files in the Content\images folder.
  • 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.
  • A ViewSwitcher controller widget (Controllers\ViewSwitcherController.cs).
  • jQuery.Mobile.MVC.dll, a DLL that provides view context extensions used to determine if view overrides exist.

The installation process also upgrades jQuery from version 1.62 to 1.63. The starter application uses jQuery 1.63. If you create a new ASP.NET MVC project, you’ll have to manually change the script references from jQuery version 1.62 to 1.63 in the layout file.

Note Verify that the jQuery and jQuery Mobile version numbers in the layout file match the version numbers in your project. If the NuGet package updates a new ASP.NET MVC 4 project you create, you will have to change MvcMobile\Views\Shared\_Layout.Mobile.cshtml to reference 1.6.3 instead of 1.6.2.

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:

p3_afterNuGet

Note If your mobile browser doesn’t display the Home, Speaker, Tag, and Date links as buttons, the reference to the jQuery Mobile script file is probably not correct. Verify that the jQuery Mobile file version referenced in the mobile layout file matches the version in the Scripts folder.

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.

p3_desktopView

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 page div element, add the following code, which renders the view-switcher widget:

@Html.Partial("_ViewSwitcher")

Here’s the completed code:

<body>
    <div class="page">
        @Html.Partial("_ViewSwitcher")
        <div id="header">

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

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

p3_desktopViewWithMobileLink

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.

p3_desktopBrowser

Improving the Speakers List

In the mobile browser, 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).

p3_speakersDeskTop

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.

p3_speakersConsistent

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;
}

Creating 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.

Copy AllSpeakers.cshtml to AllSpeakers.Mobile.cshtml. Open the AllSpeakers.Mobile.cshtml file and remove the <h2> heading element.

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>

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

p3_updatedSpeakerView1

Although the mobile view has improved, it’s difficult to navigate the long list of speakers. To fix this, 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.

ps_Data_Filter

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

ps_data_filter_SC

Improving 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.

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.

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.

p3_tags_J

Improving 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.

Copy the Views\Home\AllDates.Mobile.cshtml file to Views\Home\AllDates.Mobile.cshtml. Open the new file and remove the <h2> element.

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.

p3_dates1

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:

p3_dates2

Improving 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.

ps_data_filter_SC

Tap the Scott Hanselman link.

p3_scottHa

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.

ps_SessionsByScottHa

Improving 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.

ps_data_filter_SC

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

ps_SessionsByScottHa

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

ps_love

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:

p3_love2

Wrapup and Review

This tutorial has introduced the new mobile features of ASP.NET MVC 4 Developer Preview. The mobile features include:

  • The ability to override layout, views, and partial views, both globally and for an individual view.
  • Control over layout and partial override enforcement using the RequireConsistentDisplayMode property.
  • A view-switcher widget for mobile views than can also be displayed in desktop views.
  • Support for supporting specific browsers, such as the iPhone browser.

Posted on 21 September 2011, in ASP.NET MVC. Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: