September 2012

Volume 27 Number 09

Web Dev Report - Integrating jQuery Mobile into ASP.NET Web Forms and MVC Web Apps

By Rachel Appel | September 2012

How jQuery Mobile Works

When a mobile page renders, jQuery Mobile looks for specific HTML5 data-* attributes in ASP.NET Web Forms pages or in ASP.NET MVC views and then injects mobile-specific markup, styling, behavior and events into those elements. The jQuery Mobile library contains many data-* attributes that you can exploit in your Web pages to hook into events, perform styling, set behaviors or do whatever else you choose. This combination of data-* attributes, injected markup and CSS works together to create a consistent structure that defines how pages render as well as how navigation works.

Figure 1 shows the markup required to create a basic page template. The page begins with the customary <head> section of the document, including the requisite script references and a <viewport> tag. The viewport <meta> element sets the initial zoom setting in the browser on a device-by-device basis, creating the best possible readability experience, including Web pages without frameworks like jQuery Mobile.

Also listed in Figure 1 are the <div> elements that contain the core data-role attributes: page, header, footer and content are in the <body> section of the page. While the code in Figure 1 points to the jQuery Mobile Content Delivery Network, or CDN, note that you also have the choice of using local script references. (See Figure 5 for an example of local references in MVC.)

<!DOCTYPE html>
<html>
       <head>
       <title>Mobile Page Template</title>
       <meta name="viewport" 
          content="width=device-width, initial-scale=1">
       <link rel="stylesheet" 
          href="https://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css" />
       <script src="https://code.jquery.com/jquery-1.7.1.min.js"></script>
       <script src="https://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"></script>
</head>
<body>
<div data-role="page">
       <div data-role="header">
              <h1>Header Here</h1>
       </div>
       <div data-role="content"> 
              <p>Hello, mobile world!</p>      
       </div>
       <div data-role="footer">
<h4>Footer Here</h4>      
       </div>
</div>
</body>
</html>

Figure 1 Basic structure of a jQuery Mobile page template

The page data-* attribute inside the <div> elements notifies jQuery Mobile whether the site is single-page or multipage and determines how to navigate between pages based on that information.

jQuery Mobile supports both single-page and multipage navigation. If you’re integrating into an existing ASP.NET project, single-page navigation works best. It lets you continue to use the Web Forms Master Page model and navigate between individual pages. Navigation is set up this way because JQuery Mobile looks for an element with the data-role=”page” attribute and then treats that element as if it were a complete page. jQuery Mobile considers the fragments of HTML inside the page <div> as different roles inside that page, that is, header, content and footer.

jQuery Mobile and ASP.NET Web Forms

The goal of using any ASP.NET technology is the ability to render browser-friendly output by writing a mixture of mostly server-side but some client-side code. By integrating jQuery Mobile into Web Forms, you can continue to render browser-friendly output from the server and also target mobile devices with jQuery Mobile as your client-side framework.

You can easily retrofit jQuery Mobile into ASP.NET Web Forms. Open any existing Web Forms project and launch NuGet through the Manage NuGet Packages option of the Project menu (or right-click the project node in Solution Explorer and choose Manage NuGet Packages). You might have to search for “jQuery Mobile” and install it. Because jQuery Mobile depends on jQuery, NuGet will install files for both frameworks.

Integrating a Web Forms Master Page with jQuery Mobile is straightforward. The task is to blend the structural code from the template in Figure 1 with your existing Master Page code so that it looks similar to Figure 2. The <div class=”page”> element is perfect for the page data-role, while its children <div> elements are good choices for the header, footer and content data-roles. The <asp:ContentPlaceholder> control should go inside the content data-role.

<%@ Master Language="C#" 
    AutoEventWireup="true" 
    CodeBehind="Site.master.cs" 
    Inherits="MobileWebForms.SiteMaster" %>
<!DOCTYPE html>
<html>
<head runat="server">
    <!-- js/css references removed for brevity -->
    <asp:ContentPlaceHolder ID="HeadContent" runat="server"> 
    </asp:ContentPlaceHolder>
</head>
<body>
    <form runat="server">
    <div class="page" data-role="page">
        <div class="header" data-role="header" >
            <div class="title">
                <h1>jQuery Mobile MVC</h1>
            </div>
            <!-- menu control removed for brevity  -->
        </div>
        <div class="main" data-role="content">
            <asp:ContentPlaceHolder ID="MainContent" runat="server"/>
        </div>
        <div class="footer" data-role="footer"></div>
    </div>
    </form>
</body>
</html>

Figure 2 ASP.NET Web Forms Master Page with jQuery Mobile

Most Master Pages also contain the site navigation. To make a mobilized menu bar with the <asp:menu> control, insert the data-role=”navbar” attribute in the <asp:menu> control, even if the menu control is already inside a <div> element, as the code in Figure 3 demonstrates. Figure 3 also shows that data-role and data-* attributes work with ASP.NET server controls (in particular, the menu control) in addition to standard HTML.

 

<div class="clear hideSkiplink">
    <asp:Menu ID="NavigationMenu" 
    runat="server" 
    CssClass="menu" 
    EnableViewState="false"
    IncludeStyleBlock="false" 
    Orientation="Horizontal" 
    data-role="navbar">
        <Items>
            <asp:MenuItem NavigateUrl="~/Default.aspx" Text="Home"/>
            <asp:MenuItem NavigateUrl="~/About.aspx" Text="About"/>
        </Items>
    </asp:Menu>
</div>

Figure 3 ASP.NET menu control with data-role attribute

The bulk of the work, however, is carried out in the individual pages. Specific controls in ASP.NET Web Forms don’t always work together nicely with jQuery Mobile, so you must ensure that the output generated from the server side is compatible. This means using a few tricks like preferring template controls to full-features ones, for example, converting ListBox controls to ListView controls or using DataLists or Repeaters over DataGrids.

Figure 4 details a commonly used technique in a Web form: using a data-bound <asp:ListView> control with templates. In Figure 4, the important code to note is the <ul> tag’s data-role=”listview” attribute, which tells jQuery Mobile to modify the <ul> and its children so they will display and function with mobile style and behavior. The data-inset attribute deals with rendering inset list items, meaning that it buffers space to counterbalance the negative margin that is the default rendering of lists in HTML.

<asp:ListView ID="ListView1" runat="server" 
DataSourceID="SqlDataSource1"
EnableTheming="False" EnableViewState="False">
<ItemTemplate>
    <li >             
        <asp:HyperLink ID="HyperLink1" 
            runat="server" Text='<%# Eval("Product_Name") %>'
            NavigateUrl='<%# Eval("Product_Name", "~/products.aspx?id={0}")  %>'>
            <asp:Label ID="NameLabel" runat="server" 
                Text='<%# Eval("Product_Name") %>' />
        </asp:HyperLink><br />
   </li>
</ItemTemplate>
<LayoutTemplate>
   <ul id="listViewLayout" runat="server" 
        data-role="listview" data-inset=”true”>
        <li runat="server" id="listViewItem"></li>
    </ul>
</LayoutTemplate>
</asp:ListView>

Figure 4 ASP.NET Web Forms mobile list view

As you can see from Figure 4, most of the ASP.NET server-side code remains untouched. The extra markup for jQuery Mobile is required only when you need to mobilize elements.

Although View State assists in shielding the developer from the complexities of the stateless nature of HTTP, it also adds weight to the page that is often unacceptable in compact devices. If you’re incorporating mobile features into your application, ensure that you check View State for all controls and turn it off wherever possible. Starting with ASP.NET version 4, there are many choices for cutting down the amount of View State.

jQuery Mobile and ASP.NET MVC

If you’re just getting started with ASP.NET MVC mobile development, jQuery Mobile is available as a Mobile MVC project template in versions 3 and 4. If you’re working on a nonmobilized, standard ASP.NET MVC 3/4, or an MVC 2 app, you need to perform the same basic integration tasks as with Web Forms. As with Web Forms, using NuGet is the easiest way to get up and running with jQuery Mobile. Figure 5 shows a mobilized Razor Layout Page (conceptually the same as a Web Forms Master Page).

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
       <title>@ViewBag.Title</title>
    <meta name="viewport" content="width=device-width" />
    <link rel="stylesheet" href="~/Content/Site.css" /> 
    <script type="text/javascript" 
        src="~/Scripts/jquery-1.6.4.min.js"></script>
    <link rel="stylesheet" 
        href="~/Content/jquery.mobile-1.1.0.min.css" />
    <script type="text/javascript" 
        src="~/Scripts/jquery.mobile-1.1.0.min.js"></script>
</head>
<body>
    <div id="layoutpage" data-role="page" data-theme="a">
           <div data-role="header">
            @if (IsSectionDefined("Header")) {
                @RenderSection("Header")
            } else {
                      <h1>@ViewBag.Title</h1>
                @Html.Partial("_LogOnPartial")
            }
           </div>
           <div data-role="content">    
                  @RenderBody()
           </div>
    </div>
</body>

Figure 5 Mobilized Razor Layout Page

The Layout Page in Figure 5 shows basic HTML and Razor code. The necessary script and CSS references are in the beginning of the view, and the jQuery Mobile parts are what you might expect—the <div> elements marked with the data-role attributes. The RenderBody() method in a Layout Page belongs in the data-role element marked as “content”.

Figure 6 demonstrates a listview data-role that renders a list of links with images in a Razor view. This list is the Razor equivalent of the Web Forms code in Figure 4. Working with ASP.NET MVC views forces you to deal with bare HTML, as opposed to Web Forms, which abstract much of the HTML away in the form of server-side controls.

 

@model IEnumerable<MobileBakery.Models.Product>
@{ ViewBag.Title = "Products"; }
<ul data-role="listview">
    @foreach (var item in Model) {
    <li>
        <img src=@Url.Content("~/Content/Images/")@item.ImageName 
        alt="Image"  />
        @Html.ActionLink((string)item.Name, "Details", "Products", 
        new { id = item.Id }, null)
   </li>}
</ul>

Figure 6 A listview data-role in Razor

As you can see, incorporating jQuery Mobile into Razor views is quite easy.

Mobile Site Strategies

Mobilizing Web sites isn’t just about shrinking pages. It’s also about presenting the right content, in the right format, at the right time. Sometimes mobilizing a Web site is as simple as modifying pages and delivering a smaller representation of those pages. Other times, business requirements make it impossible to have a simple one-to-one relationship between a page full of content for a desktop browser and that same content in a mobile browser, so you might need to rework how you present mobile content—and decide how much of it can go on each page.

There are three ways to enhance the structuring of Web sites so that you can have the smallest codebase possible while serving the greatest number of user devices:

  • Switch only the Master/Layout Pages between desktop and mobile versions
  • Switch out entire sites between desktop and mobile versions
  • Use a hybrid site model

The business requirements of your particular project will dictate which route to take, but switching Layout Pages takes little effort and can give you a big bang for the buck. For example, you need very little code to swap an MVC Layout Page.

@{ Layout = Request.Browser.IsMobileDevice
 ? "~/Views/Shared/_MobileLayout.cshtml"
 : "~/Views/Shared/_Layout.cshtml"; }

Because jQuery Mobile looks for the data-role attributes, you can put them into a single view but change only the underlying Layout Page at run time. During run time, the browser (any browser) will then ignore the data-role attributes that jQuery Mobile normally uses for injection unless the Layout Page with the mobile script references is the one the browser requested.

Another consideration when mobilizing Web sites is the use of CSS media queries. Media queries are CSS3 features that allow you to specify “at” rules, or rules in CSS that begin with the @ character. These rules specify what the browser must do, depending on the type of device or the screen size. For example, the following query detects whether the browser’s maximum width is 480px, meaning a mobile device.

@media screen and (max-width:480px) { … }

If this query condition is met, the CSS that corresponds to it renders in the browser. You can use complex expressions targeting a variety of conditions in CSS media queries.

Summary

Going mobile requires some planning and strategy; however, implementing new mobilized sites and integrating existing ones with jQuery Mobile relieves much of the pain around mobilization because of the way jQuery Mobile uses new, unobtrusive features from HTML5, CSS3 and JavaScript in a simple way (e.g., use of data-* attributes). Although the use of server-side controls in Web Forms might make for some bumps in the mobilized road, the simplicity of jQuery Mobile holds true for both ASP.NET Web Forms and MVC.


Rachel Appel is a developer evangelist at Microsoft New York City. You can reach her via her Web site athttps://rachelappel.comor by e-mail atrachel.appel@microsoft.com. *You can also follow her latest updates on Twitter at @rachelappel.*