Мобильные приложения

118

В этой последней статье будут показаны новые возможности ASP.NET Framework 4.5, доступные для ориентации контента на различные виды устройств. Мобильные устройства становятся все более мощными, а их браузеры все больше соответствуют стандартам, но возможности варьируются и не все браузеры выполняют визуализацию согласованным образом - к тому же не каждая HTML-разметка максимально эффективно использует функции устройства.

При написании веб-приложения можно принять один из трех подходов к работе с мобильными устройствами. Все эти подходы описаны ниже:

Пример проекта

Мы продолжим работу с проектом ClientDev, созданным ранее. Вдобавок мы создали веб-форму по имени Simple.aspx, контент которой приведен в примере ниже:

<%@ Page Language="C#" AutoEventWireup="true" 
   CodeBehind="Simple.aspx.cs" Inherits="ClientDev.Simple" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title></title>
    <style>
        div { margin-bottom: 10px; }
        .message { font-size:xx-large; }
    </style>
</head>
<body>
    <div>
        <span class="message">Это страница Simple.aspx</span>
    </div>
    <div>
        <button>Кнопка 1</button>
        <button>Кнопка 2</button>
    </div>
</body>
</html>

Мы собираемся показать в этой статье, каким образом проводить различия контента на основе устройства, выполняющего запрос, поэтому веб-форма Simple.aspx содержит литеральную строку, которая идентифицирует запрошенную веб-форму, и пару элементов button. Чтобы увидеть результирующий вывод, запустите приложение и запросите веб-форму Simple.aspx:

Вывод из веб-формы Simple.aspx

Добавление пакета jQuery Mobile

В проект понадобится добавить дополнительный пакет NuGet. Выберите пункт Manage NuGet Packages (Управлять пакетами NuGet) в меню Project (Проект) среды Visual Studio, чтобы открыть окно Manage NuGet Packages (Управление пакетами NuGet). Затем выберите категорию Online (Онлайновые) в левой панели, найдите и установите пакет jQuery.Mobile. Этот пакет добавляет в папку Scripts файлы библиотеки jQuery Mobile, а в папку Content - поддерживающие стили CSS.

В примере ниже показано содержимое файла App_Start\BundleConfig.cs после добавления в него пакетов сценариев и таблиц стилей для библиотеки jQuery Mobile:

using System;
using System.Web.Optimization;
using System.Web.UI;

namespace ClientDev
{
    public class BundleConfig
    {
        public static void RegisterBundles(BundleCollection bundles)
        {
            // ...

            Bundle jqmobile = new ScriptBundle("~/bundle/jquerymobile")
                .Include("~/Scripts/jquery-{version}.js",
                    "~/Scripts/jquery.mobile-{version}.js");

            Bundle jqmobileCSS =
                new StyleBundle("~/bundle/jquerymobileCSS")
                    .Include("~/Content/jquery.mobile-{version}.css");

            // ...
			
            bundles.Add(jqmobile);
            bundles.Add(jqmobileCSS);
        }
    }
}

Идентификация мобильных устройств

В классе HttpRequest определено свойство Browser, которое возвращает объект HttpBrowserCapabilities. Этот объект предоставляет информацию о браузере, который выполнил запрос. В примере ниже демонстрируется использование этого средства внутри веб-формы Simple.aspx:

<%@ Page Language="C#" AutoEventWireup="true" 
   CodeBehind="Simple.aspx.cs" Inherits="ClientDev.Simple" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title></title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        div { margin-bottom: 10px; }
        .message { font-size:xx-large; }
    </style>
</head>
<body>
    ...
    <div>Это <%= Request.Browser.IsMobileDevice ? "" : "не" %> мобильное устройство</div>
    ...
</body>
</html>

Мы добавили к веб-форме фрагмент кода, который вставляет значение свойства IsMobileDevice, представляющего собой самое полезное свойство из числа доступных в классе HttpBrowserCapabilties. Другие полезные свойства, связанные с возможностями браузера, перечислены в статье Работа с разными браузерами.

Обратите внимание на то, что мы также добавили к веб-форме элемент <meta>. Многие мобильные браузеры предполагают, что HTML-контент был разработан для настольного браузера, поэтому сжимают его с целью отображения как можно большего объема информации. После этого пользователи увеличивают интересующие их части страницы. Элемент <meta>, добавленный к веб-форме, отключает это средство и гарантирует, что мобильные браузеры будут отображать контент без масштабирования.

Доступно намного большее количество свойств, однако они не особенно полезны теперь, когда мобильные устройства обладают почти такими же возможностями, как их настольные аналоги. Относительно этих свойств важно отметить, что их значения получаются не из запроса. Причина в том, что при запрашивании контента протокол HTTP не требует от устройств предоставления деталей такого уровня. Вместо это информация, доступная в запросе, особенно заголовок user-agent, применяется для идентификации записи в файлах браузеров. Это статический набор текстовых файл включенный в платформу .NET Framework, в которых описаны наиболее распространенные браузеры.

Увидеть изменение значения свойства IsMobileDevice можно, запросив веб-форму Simple.aspx в эмуляторе Opera Mobile:

Отображение веб-формы Simple.aspx в эмуляторе Opera Mobile

На рисунке показана альбомная ориентация профиля HTC Desire. Эмулятор способен моделировать широкий спектр смартфонов и планшетных устройств, а также различные типы ввода, включая сенсорный. Это не является заменой тестирования на реальных устройствах, но мы находим эмулятор очень удобным на ранних стадиях разработки.

Загрузить этот эмулятор вы можете по адресу - Opera Mobile Emulator.

Переключение мастер-страниц для мобильных устройств

Теперь, когда известно, как обнаруживать мобильные устройства, можно приступать к настройке контента для мобильных устройств различными способами. Простейший способ предусматривает установку мастер-страницы на основе значения свойства IsMobileDevice. Этот прием удобен, когда нужно предоставить один и тот же базовый контент всем устройствам, но с некоторыми корректировками в стиле. Чтобы продемонстрировать, как это делается, мы создали новую мастер-страницу по имени Site.Master, контент которой приведен в примере ниже:

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="ClientDev.Site" %>
<%@ Register Src="~/ViewSwitcher.ascx" TagPrefix="friendlyUrls" TagName="ViewSwitcher" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title></title>
    <style>
        div { margin-bottom: 10px; }
        .message { font-size:xx-large; }
    </style>
</head>
<body>
    <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server" />
    <div>
        Этот текст в компоновке Site.master
    </div>
</body>
</html>

Эта мастер-страница содержит элемент <style>, который использует веб-форма Simple.aspx, а также сообщение, указывающее на факт применения данной мастер-страницы. Нам нужна ясная информация об использовании страницы Site.Master, потому что мы также создаем мастер-страницу под названием Site.Mobile.Master:

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.Mobile.master.cs" Inherits="ClientDev.Site_Mobile" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title></title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        div { margin-bottom: 10px; }
        span.message { font-size: xx-large; font-family: sans-serif;
                       color: white; background: black; }
    </style>
</head>
<body>
    <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server" />
    <div>
        Этот текст в компоновке Site.Mobile.master
    </div>
</body>
</html>

Хотя вторая мастер-страница проста, но в нее был помещен элемент <meta>, который применялся для мобильных браузеров в файле Site.Mobile.Master, изменены стили CSS и в элемент <div> включено сообщение с именем мастер-страницы. В примере ниже приведен переделанный контент веб-формы Simple.aspx с учетом модели с мастер-страницами:

<%@ Page Language="C#" AutoEventWireup="true" MasterPageFile="~/Site.Master"
     CodeBehind="Simple.aspx.cs" Inherits="ClientDev.Simple" %>

<asp:Content ContentPlaceHolderID="ContentPlaceHolder1" ID="Content1" runat="server">
    <div>
        <span class="message">Это страница Simple.aspx</span>
    </div>
    <div>Это <%= Request.Browser.IsMobileDevice ? "" : "не" %> мобильное устройство</div>
    <div>
        <button>Кнопка 1</button>
        <button>Кнопка 2</button>
    </div>
</asp:Content>

Последний шаг связан с добавлением в класс отделенного кода выбора мастер-страницы, которую будет использовать веб-форма, на основе того, идентифицирован ли браузер, отправивший запрос, как функционирующий на мобильном устройстве. Это делается в примере ниже, в котором показано содержимое файла отделенного кода Simple.aspx.cs:

using System;

namespace ClientDev
{
    public partial class Simple : System.Web.UI.Page
    {
        protected void Page_PreInit(object sender, EventArgs e)
        {
            this.MasterPageFile = Request.Browser.IsMobileDevice ?
                "Site.Mobile.Master" : "Site.Master";
        }
    }
}

Свойство MasterPageFile указывает путь к мастер-странице, которая будет применяться для визуализации веб-формы, и его значение устанавливается на основе свойства Request.Browser.IsMobileDevice. Мастер-страница используется в начале жизненного цикла страницы, поэтому свойство MasterPageFile должно устанавливаться в ответ на событие PreInit. В результате мы применяем разную разметку и контент в зависимости от вида браузера, запросившего веб-форму, что и можно видеть на рисунке ниже, на котором веб-форма Simple.aspx отображается в настольной версии браузера Google Chrome и в эмуляторе Opera Mobile:

Изменение мастер-страницы для мобильных устройств

Использование библиотек JavaScript через мастер-страницу

Для отдельного контента все, что требуется сделать - это применить другие стили, представив HTML-контент подходящим для устройства способом. Можно также воспользоваться мастер-страницей, специфичной для мобильного устройства, чтобы изменить библиотеки, которые отправляются разным типам клиентов. В частности, это удобно при работе с такими инструментальными наборами для построения пользовательских интерфейсов с помощью JavaScript, как jQuery Mobile.

Библиотека jQuery Mobile трансформирует HTML-документы, делая их более доступными на мобильных устройствах. Элементы вроде кнопок становятся крупнее и более подходящими для сенсорных взаимодействий. В примере ниже демонстрируется применение библиотеки jQuery Mobile в файле Site.Mobiie.Master:

<%@ Master Language="C#" AutoEventWireup="true" 
   CodeBehind="Site.Mobile.master.cs" Inherits="ClientDev.Site_Mobile" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title></title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        div { margin-bottom: 10px; }
        span.message { font-size: xx-large; font-family: sans-serif;
                       color: white; background: black; }
    </style>
    <%: System.Web.Optimization.Styles.Render("~/bundle/jquerymobileCSS") %>
    <%: System.Web.Optimization.Scripts.Render("~/bundle/jquerymobile") %>
</head>
<body>
    <div data-role="page">
        <div data-role="content">
            <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server" />
        </div>
        <div data-role="footer">
            Этот текст в компоновке Site.Mobile.master
        </div>
    </div>
</body>
</html>

Мы добавили пакеты jQuery Mobile, определенные в начале этой статьи, и предусмотрели несколько элементов <div> с атрибутами data-role вокруг контента веб-формы. Библиотека jQuery Mobile идентифицирует разные категории контента с использованием атрибутов data-role, поэтому элемент <div> с атрибутом data-role, установленным в footer, стилизуется как фиксированный нижний колонтитул независимо от типа элемента. Чтобы просмотреть результат применения jQuery Mobile, запустите приложение и запросите веб-форму Simple.aspx в эмуляторе Opera Mobile:

Результат использования библиотеки jQuery Mobile внутри мастер-страницы для мобильных устройств

Доставка разных веб-форм

Другой подход предусматривает создание и сопровождение отдельных наборов веб-форм, ориентированных на мобильные устройства. Это удобно, когда мобильным пользователям нужно обеспечить отличающийся интерфейс. Можно либо добавлять, либо удалять функциональность, или же реструктурировать функциональность, предлагаемую пользователям настольных браузеров, чтобы лучше соответствовать экранам мобильных устройств и сенсорным взаимодействиям.

Для демонстрации этого подхода мы будем применять пакет Microsoft ASP.NET Friendly URLs. Он позволяет не только опускать расширение .aspx в запросах к веб-формам (так что можно запрашивать /Simple.aspx с помощью URL вида /Simple), но также поддерживает доставку разных веб-форм на мобильные устройства.

Установка и конфигурирование пакета

Выберите пункт Manage NuGet Packages в меню Project среды Visual Studio, чтобы открыть окно Manage NuGet Packages. Затем выберите категорию Online в левой панели, найдите и установите пакет Microsoft.AspNet.FriendlyUrls. Вы заметите, что в проект было добавлено несколько новых ссылок на сборки, а также пользовательский элемент управления под названием ViewSwitcher.aspx (к которому мы еще вернемся). Вы можете получить вопрос о необходимости замены файла Site.Mobile.Master. Не делайте этого, поскольку будет утерян контент, созданный ранее. Поддержку дружественных URL понадобится включить в файле App_Start\RouteConfig.cs, как показано в примере ниже:

using System.Web.Routing;
using System.Web.Http;
using Microsoft.AspNet.FriendlyUrls;

namespace ClientDev
{
    public static class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.MapHttpRoute(name: "WebApiRoute",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional });

            routes.EnableFriendlyUrls();
        }
    }
}

Доставка специального контента

Пакет Microsoft ASP.NET Friendly URLs доставляет специальный контент на мобильные устройства, когда находит веб-форму, которая соответствует текущему запросу и имеет файловый суффикс *.Mobile.aspx.

Для получения мобильной версии веб-формы Simple.aspx мы должны создать новую веб-форму под названием Simple.Mobile.aspx. Ее контент приведен в примере ниже:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Simple.Mobile.aspx.cs" 
    Inherits="ClientDev.Simple_Mobile" MasterPageFile="~/Site.Mobile.Master" %>

<asp:Content ContentPlaceHolderID="ContentPlaceHolder1" ID="Content1" runat="server">
    <div>
        <span class="message">Это страница Simple.Mobile.aspx</span>
    </div>
    <div>Это <%= Request.Browser.IsMobileDevice ? "" : "не" %> мобильное устройство</div>
    <div>
        <button>Кнопка 1</button>
        <button>Кнопка 2</button>
    </div>
</asp:Content>

Веб-форма имеет такую же базовую структуру, как и Simple.aspx, но в ней изменено значение атрибута MasterPageFile для указания на мобильную мастер-страницу. Кроме того, изменен контент элемента <span>, чтобы отразить факт отображения этой веб-формы. Чтобы увидеть результат, запустите приложение и запросите URL вида /Simple. Настольный и мобильный браузеры получат соответствующие версии веб-формы:

Доставка разных веб-форм на основе типа устройства

Пакет Microsoft ASP.NET Friendly URLs работает только с дружественными URL. Это означает, что если мобильный браузер запрашивает /Simple, то он получит веб-форму Simple.Mobile.aspx. Однако если мобильный браузер запрашивает /Simple.aspx, библиотека Microsoft ASP.NET Friendly URLs не перехватит этот запрос и будет доставлена веб-форма, предназначенная для настольного браузера.

В состав пакета Microsoft ASP.NET Friendly URLs входит пользовательский элемент управления ViewSwitcher, который можно помещать внутрь веб-форм или мастер-страниц для предоставления пользователю средства переключения между мобильной и настольной версиями веб-формы.

Добавлять этот элемент управления в приложение имеет смысл, если оно доставляет мобильным устройствам специальные веб-формы, поскольку некоторые мобильные устройства вполне способны отображать контент, предназначенный для настольного браузера. Навязывание пользователю мобильной версии приложения может стать причиной его недовольства. В примере ниже демонстрируется применение элемента управления ViewSwitcher в файле Site.Mobile.Master:

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.Mobile.master.cs" Inherits="ClientDev.Site_Mobile" %>
<%@ Register Src="~/ViewSwitcher.ascx" TagPrefix="friendlyUrls" TagName="ViewSwitcher" %>

<!DOCTYPE html>
<html>
<head runat="server">
    ...
</head>
<body>
    <div data-role="page">
        ...
        <div data-role="footer">
            <friendlyUrls:ViewSwitcher runat="server" />
        </div>
    </div>
</body>
</html>

Этот же элемент управления необходимо добавить и в файл Site.Master, чтобы пользователь мог переключаться обратно:

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="ClientDev.Site" %>
<%@ Register Src="~/ViewSwitcher.ascx" TagPrefix="friendlyUrls" TagName="ViewSwitcher" %>

<!DOCTYPE html>
<html>
<head runat="server">
    <title></title>
    <style>
        div { margin-bottom: 10px; }
        .message { font-size:xx-large; }
    </style>
</head>
<body>
    <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server" />
    <div>
        <friendlyUrls:ViewSwitcher runat="server" />
    </div>
</body>
</html>

Элемент управления ViewSwitcher помещает на страницу ссылки, которые позволяют пользователям выбирать тип получаемого контента. Как показано на рисунке ниже, это применимо к настольным и мобильным браузерам:

Переключение между мобильной и настольной версиями веб-формы

Хотя веб-формы изменились, мастер-страница осталась той же самой. Причина в том, что пакет Microsoft ASP.NET Friendly URLs меняет мастер-страницу динамически для запросов.

HTTP-модуль для мобильных устройств

В завершение этой статьи мы хотим показать, насколько тесно функциональные возможности ASP.NET Framework сочетаются друг с другом. С этой целью мы создадим модуль, который будет автоматически отображать запросы к веб-форме вроде Simple.aspx на веб-форму Simple.Mobile.aspx, предназначенную для мобильных устройств. Пакет Microsoft ASP.NET Friendly URLs будет делать это для маршрутизируемых им запросов, а наш модуль дополнит его функциональность, обрабатывая непосредственно запросы к веб-формам.

В примере ниже приведено содержимое добавленного к проекту файла класса MobileModule.cs, в котором можно видеть, как все реализовано:

using System.IO;
using System.Web;

namespace ClientDev
{
    public class MobileModule : IHttpModule
    {
        public void Dispose() 
        {
            // Ничего не делать
        }

        public void Init(HttpApplication context)
        {
            context.BeginRequest += (src, args) =>
            {
                string requested = context.Request.Path;
                if (requested.ToLower().EndsWith(".aspx")
                        && !requested.ToLower().EndsWith(".mobile.aspx")
                        && context.Request.Browser.IsMobileDevice)
                {
                    string[] pathElems = requested.Split('.');
                    pathElems[pathElems.Length - 1] = "Mobile.aspx";
                    string target = string.Join(".", pathElems);
                    if (File.Exists(context.Request.MapPath(target)))
                    {
                        context.Server.Transfer(target);
                    }
                }
            };
        }
    }
}

В модуле MobileModule мы обрабатываем событие BeginRequest для исследования запросов. С помощью свойства HttpRequest.Path мы проверяем, нацелен ли запрос на файл *.aspx, а посредством свойства IsMobileDevice выясняем, поступил ли он из мобильного устройства. Мы также проверяем, не предназначен ли запрос для веб-формы, имя которой завершается на .Mobile.aspx, т.к. мы не хотим вмешиваться в запросы, которые уже направлены на мобильную версию веб-формы.

Мы также не хотим вмешиваться в запросы, для которых не предусмотрено мобильных веб-форм, поэтому с помощью базовых средств обработки строк C# отображаем строку наподобие /Simple.aspx на /Simple.Mobile.aspx и затем используем метод HttpRequest.MapPath() для выяснения, где файл мобильной веб-формы предположительно находится на диске, если он существует. Метод MapPath() преобразует имя файла, не проверяя, существует ли файл, поэтому мы применяем метод File.Exists(), чтобы узнать, доступна ли мобильная форма.

Если запрос нацелен на файл *.aspx, не относится к мобильной версии веб-формы, поступает из мобильного устройства и доступна мобильная веб-форма, мы используем метод HttpServerUtility.Transfer() для генерации вывода из мобильной версии той веб-формы, что была запрошена.

Модуль должен быть зарегистрирован в файле Web.config, как показано в примере ниже:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  ...
  <system.webServer>
    <modules>
      <add name="Mobile" type="ClientDev.MobileModule"/>
    </modules>
    ...
  </system.webServer>
</configuration>

Благодаря добавлению этого модуля, мобильные устройства могут запрашивать веб-форму, подобную Simple.aspx, и получать взамен контент веб-формы Simple.Mobile.aspx.

Итак, в этой статье были продемонстрированы возможности, которые ASP.NET Framework предлагает для обнаружения мобильных устройств и настройки отправляемого им контента. Мы показали, как изменять мастер-страницу для мобильных устройств и доставлять мобильные версии веб-форм.

Пройди тесты
Лучший чат для C# программистов