ASP.NET MVC 4

ASP.NET MVC 4

Адам Фриман

Работа с мобильными устройствами

Вы будете часто оптимизировать приложения MVC Framework для мобильных устройств, а для этого необходимо адаптировать контент, который вы предоставляете пользователю, а также учитывать доступные функции и ограничения устройства. Между мобильными устройствами и настольными компьютерами есть много различий, но больше всего хлопот вызывают сенсорный ввод и ограниченный размер экрана. Чтобы в представлениях, которые визуализируются для мобильного клиента, можно было использовать сенсорный ввод, необходимы элементы большего размера и свободное пространство между ними, чтобы ввод был достаточно точным. Также необходимо убедиться, что контент можно прочитать на маленьком экране.

Мы не собираемся вдаваться в подробности разработки для мобильных устройств, но продемонстрируем, как MVC Framework помогает обеспечить поддержку обычных и мобильных клиентов в приложении.

Подсказка

Когда вы создаете новый проект MVC Framework, доступна опция Mobile template, но это всего лишь вариант шаблона Internet, в котором добавлена поддержка библиотеки jQuery Mobile. Нам очень нравится jQuery Mobile, и, как вы уже догадались, Адам подробно описал ее в других своих книгах. Однако нам не нравится шаблон Mobile, поскольку он добавляет стандартные представления и контроллеры для аутентификации, которые, по нашему мнению, не очень хорошо работают. Вместо этого мы рекомендуем вам установить jQuery Mobile и другие необходимые библиотеки JavaScript с помощью NuGet.

Пересматриваем приложение

Лучше всего начать оптимизировать приложение для мобильных устройств с самого начала разработки проекта. Здесь мы будем делать все наоборот, а именно - добавим поддержку в существующее приложение ClientFeatures, на примере которого мы продемонстрировали, как использовать связки.

Для начала попытаемся понять, как наше приложение выглядит на различных мобильных устройствах. Для этого мы будем использовать эмулятор Opera Mobile Emulator, который можно бесплатно скачать с www.opera.com/developer/tools/mobile. Конечно, ничем нельзя заменить тестирование мобильного приложения на реальных мобильных устройствах, но Opera Mobile Emulator позволит быстро оценить, где мы находимся. Он распространяется бесплатно, обеспечивает верную эмуляцию браузера Opera Mobile, который используется на многих мобильных устройствах, и позволяет протестировать различные профили и возможности аппаратного обеспечения.

Подсказка

Есть другие эмуляторы, в том числе для платформ Windows Phone, Android и Blackberry. Как правило, они работают довольно медленно и трудны в использовании, потому что они эмулируют целую мобильную операционную систему, а не только браузер. Мы еще не нашли ни одного вменяемого эмулятора iPhone для Windows PC: в них обычно используется Windows-версия Safari, которая отличается от версии IOS и похожа на неудачную копию браузера Apple.

На рисунке 24-5 показано, как отображается в мобильном браузере представление /Home/MakeBooking. В эмуляторе мы использовали профиль HTC Hero, который имитирует типичное, ничем не выдающееся мобильное устройство с сенсорным дисплеем 320 × 480 пикселей и разрешением 180 пикселей на дюйм.

Рисунок 24-5: Приложение в мобильном браузере

Так как это очень простое приложение, оно не так уж плохо отображается на экране. Если придираться, то можно сказать, что элементы расположены не лучшим образом для использования на сенсорном экране. Большинство реальных приложений, разработанных и протестированных в браузерах для РС, в мобильных браузерах выглядят ужасно.

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

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

В качестве примера мы создали новый файл представления под названием Views/Home/MakeBooking.Mobile.cshtml. Обратите внимание на фрагмент .Mobile перед расширением файла. Содержимое представления показано в листинге 24-13.

Листинг 24-13: Представление /Views/Home/MakeBooking.Mobile.cshtml
@model ClientFeatures.Models.Appointment

@{
	ViewBag.Title = "Make A Booking";
	AjaxOptions ajaxOpts = new AjaxOptions
	{
		OnSuccess = "processResponse"
	};
}

<h4>This is the MOBILE View</h4>

@section scripts {
	<script src="~/Scripts/Home/MakeBooking.js" type="text/javascript"></script>
}

<div id="formDiv" class="visible">
	@using (Ajax.BeginForm(ajaxOpts))
	{
		@Html.ValidationSummary(true)
		<p>@Html.ValidationMessageFor(m => m.ClientName)</p>
		<p>Name:</p><p>@Html.EditorFor(m => m.ClientName)</p>
		<p>@Html.ValidationMessageFor(m => m.Date)</p>
		<p>Date:</p><p>@Html.EditorFor(m => m.Date)</p>
		<p>@Html.ValidationMessageFor(m => m.TermsAccepted)</p>
		<p>@Html.EditorFor(m => m.TermsAccepted) Terms & Conditions</p>
		<input type="submit" value="Make Booking" />
	}
</div>

<div id="successDiv" class="hidden">
	<h4>Your appointment is confirmed</h4>
	<p>Your name is: <b id="successClientName"></b></p>
	<p>The date of your appointment is: <b id="successDate"></b></p>
	<button id="backButton">Back</button>
</div>

Мы внесли небольшие коррективы в это представление, чтобы метки для элементов input отображались отдельно, а также изменили содержание элемента h4 title, чтобы стало очевидно, какое представление отображается.

MVC Framework применяет мобильное представление автоматически. Если вы запустите приложение и перейдете по ссылке /Home/MakeBooking в браузере настольного компьютера, то увидите HTML, сгенерированный для представления /Views/Home/MakeBooking.cshtml. Но если вы перейдете по той же ссылке в эмуляторе мобильного браузера, то увидите HTML, сгенерированный для представления /Views/Home/MakeBooking.Mobile.cshtml, как показано на рисунке 24-6.

Рисунок 24-6: Переход по ссылке в настольном и мобильном браузерах

Способ обнаружения мобильных браузеров немного странный и опирается на набор текстовых файлов, которые входят в.NET Framework. Мы нашли их в C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\Browsers, но в других операционных системах директория может отличаться. Здесь находится ряд файлов, каждый из которых идентифицирует мобильный браузер – есть файл и для Opera Mobile. Когда MVC Framework получает запрос от мобильного эмулятора, он смотрит на строку UserAgent, которую отправляют все браузеры, и определяет, что запрос был отправлен с мобильного устройства; далее используется представление MakeBooking.Mobile.cshtml.

Создаем пользовательские режимы отображения

По умолчанию MVC Framework обнаруживает только мобильные устройства и рассматривает их в одной категории. Если вы хотите уточнить, как отвечать различным типам устройств, то можете создать свои собственные режимы отображения. Чтобы это продемонстрировать, мы будем использовать профиль Amazon Kindle Fire, который имеется в Opera Mobile Emulator. Opera Mobile, установленная на планшете, посылает строку UserAgent, которая не соответствует тому, что ожидает .NET Framework от Opera Mobile; таким образом, к устройству отправляется стандартное представление MakeBooking.cshtml.

В листинге 24-14 показано, как мы изменили файл Global.asax, чтобы создать новый режим отображения для браузера Opera Tablet.

Листинг 24-14: Создаем новый режим отображения в файле Global.asax
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using System.Web.WebPages;

namespace ClientFeatures
{
	public class MvcApplication : System.Web.HttpApplication
	{
		protected void Application_Start()
		{
			DisplayModeProvider.Instance.Modes.Insert(0,
				new DefaultDisplayMode("OperaTablet")
				{
					ContextCondition = (context => context.Request.UserAgent.IndexOf
						("Opera Tablet", StringComparison.OrdinalIgnoreCase) >= 0)
				});
			AreaRegistration.RegisterAllAreas();
			WebApiConfig.Register(GlobalConfiguration.Configuration);
			FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
			RouteConfig.RegisterRoutes(RouteTable.Routes);
			BundleConfig.RegisterBundles(BundleTable.Bundles);
		}
	}
}

Статическое свойство DisplayModeProvider.Instance.Modes возвращает коллекцию, с помощью которой мы можем определить пользовательские режимы отображения; для этого необходимо создать экземпляр объекта DefaultDisplayMode и установить в качестве значения свойства ContextCondition лямбда-выражение, которое получает объект HttpContextBase и возвращает логическое значение. Аргументом конструктора для класса DefaultDisplayMode является имя режима отображения, которое будет использоваться для поиска макетов и представлений, адаптированных для конкретного типа устройств. Мы указали OperaTablet, что означает, что MVC Framework будет искать такие представления, как /Views/Home/MakeBooking.OperaTable.cshtml.

Подсказка

Обратите внимание, что мы использовали метод Insert, чтобы поместить объект DefaultDisplayMode с нулевым индексом в коллекции, которую возвращает свойство DisplayModeProvider.Instance.Modes. MVC Framework проверяет режимы отображения по очереди и останавливает поиск, если выражение ContextCondition какого-либо режима возвращает true. Есть резервный режим отображения, который будет соответствовать любому запросу и использовать представление по умолчанию (т.е. без дополнений OperaTable или Mobile). Мы должны гарантировать, что наш режим отображения находится в очереди перед резервным вариантом.

Мы используем объект HttpContextBase, чтобы решить, соответствует ли полученный запрос искомому режиму отображения. Мы проверяем, содержит ли свойство Request.UserAgent значение Opera Tablet, и если да, то возвращаем true.

Чтобы воспользоваться этим режимом, мы создали новое представление под названием /Views/Home/MakeBooking.OperaTablet.cshtml, которое показано в листинге 24-15.

Листинг 24-15: Содержимое файла MakeBooking.OperaTablet.cshtml
@model ClientFeatures.Models.Appointment

@{
	ViewBag.Title = "Make A Booking";
	AjaxOptions ajaxOpts = new AjaxOptions
	{
		OnSuccess = "processResponse"
	};
}

<h4>This is the OPERA TABLET View</h4>

@section scripts {
	<script src="~/Scripts/Home/MakeBooking.js" type="text/javascript"></script>
}

<div id="formDiv" class="visible">
	@using (Ajax.BeginForm(ajaxOpts))
	{
		@Html.ValidationSummary(true)
		<p>@Html.ValidationMessageFor(m => m.ClientName)</p>
		<p>Name:</p><p>@Html.EditorFor(m => m.ClientName)</p>
		<p>@Html.ValidationMessageFor(m => m.Date)</p>
		<p>Date:</p><p>@Html.EditorFor(m => m.Date)</p>
		<p>@Html.ValidationMessageFor(m => m.TermsAccepted)</p>
		<p>@Html.EditorFor(m => m.TermsAccepted) Terms & Conditions</p>
		<input type="submit" value="Make Booking" />
	}
</div>

<div id="successDiv" class="hidden">
	<h4>Your appointment is confirmed</h4>
	<p>Your name is: <b id="successClientName"></b></p>
	<p>The date of your appointment is: <b id="successDate"></b></p>
	<button id="backButton">Back</button>
</div>

Здесь мы внесли только одно изменение - в элемент h4, который сообщает нам, какое используется представление. Если мы запустим Opera Mobile Emulator с профилем Kindle File и перейдем по ссылке /Home/MakeBooking, то увидим, что используется наше новое представление, как показано на рисунке 24-7.

Рисунок 24-7: Результат создания пользовательского режима отображения

Очевидно, что в реальном проекте мы сделали бы немного больше изменений, учитывая размер экрана и необходимость сенсорного ввода; но в этой главе мы остановимся на краткой демонстрации того, как использовать пользовательские режимы отображения для точного контроля над представлениями.

Внимание!

Будьте осторожны при создании пользовательских режимов отображения. Очень легко захватить неправильные запросы от клиентов или пропустить тонкие различия между версиями браузера, работающими на конкретных типах мобильных устройств. Мы рекомендуем тщательное тестирование на различных устройствах.

или RSS канал: Что новенького на smarly.net