- PVSM.RU - https://www.pvsm.ru -
ASP.NET MVC 4 вышел с очень ожидаемой и долгожданной новой возможностью — то, что по английски называют Mobile Features — поддержкой мобильных устройств. По большому счету, название сразу удивило, так как немного расходится с техническим описанием нововведения. Но промоушен — есть промоушен. Все упоминания про шаблоны страниц (layout) с поддержкой HTML 5, указание viewport, CSS media — все это к MVC фреймворку непосредственно отношения не имеет.
К новой возможности самого фреймворка можно отнести только два пункта:
И здесь сразу стоит заметить, что слово «мобильный» упоминается исключительно в рекламных целях. MVC 4 позволяет создавать несколько View для каждой из требуемых страниц и определять для какого браузера каждая из них должна показываться. То есть, возможности ни коем образом не ограничиваются именно мобильными браузерами.
Реализация данной возможности очень проста. Это просто «hook» во ViewEngine.
Вы делаете разные страницы (Views) для разных устройств или браузеров. Именуете файлы добавляя ключевое слово:
Задаете критерий по которому будет выбираться нужная View — пользуясь DisplayModeProvider задаете нужные DefaultDisplayMode с нужным именем.
DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("iPhone")
{
ContextCondition = (context => context.GetOverriddenUserAgent().IndexOf
("iPhone", StringComparison.OrdinalIgnoreCase) >= 0)
});
В рантайме, когда отработает метод контроллера, подготовленный ViewResult передается во View Engine, проверяются условия DisplayModeProvider-a, он изменяет имя файла View, которое нужно загрузить.
Можем конечно. Но только в очень простых случаях. Основное неудобство именно в том, что все View, которые вы делаете для страницы обрабатываются одним и тем же методом контроллера. Рано или поздно, это становится проблемой.
Уже настало время, когда веб-сайт должен поддерживать браузеры не только на десктопных компьютерах, ноутбуках и мобильных устройствах, но еще и на телевизорах. Причем к мобильным устройствам относятся обычные телефоны, смартфоны и планшетные компьютеры. И согласитесь — если внешний вид на планшете и смартфоне еще может быть одинаковым, с одними и теми же JavaScript виджетами, то для обычных сотовых телефонов, коих еще много, такое же представление и такие же возможности Web UI обеспечить сложно.
Поддержка одновременно смартфонов и планшетов с первого взгляда выглядит не такой сложной — разница в размере экрана. Но на большей площади можно разместить больше информации или больше пользовательских функций, а не просто увеличить размер картинок.
Поддержка телевизоров выглядит очень простой задачей. Full HD означает одинаковый размер экрана в пикселах. Но на этом плюсы заканчиваются.
Оказывается, если Ваш сайт открыли с телевизора, он мог быть открыт в браузерах на:
Сделать версию сайта одинаково удобную для всех этих устройств мало реалистично. Если вы хотите воспользоваться всеми дополнительными возможностями, которые эти устройства предоставляют Вам как разработчикам — то делать это в одной версии сайта становится не рационально. А некоторые возможности, поверьте, стоят того, чтобы ими пользоваться.
Например, на XBOX работает обычный Internet Explorer, ширина экрана вполне достаточная для работы с обычной десктопной версией сайта, но пользователь вынужден на джойстике возить по экрану курсор. Для того, чтобы нажать на кнопку на экране ему требуется навести на нее курсор и нажать кнопку на джойстике. Становится очевидным, что более подходящий интерфейс — это интерфейс для планшетов, с большими прямоугольными кнопками. Комбобоксы также не удобны. Пролистывать страницу на джойстике достаточно удобно.
На SmartTV Вам придется расчитывать на то, что нет курсора и пользователь бегает по кнопкам и инпутам на странице нажимая кнопки вверх/вниз/влево/вправо на пульте. Чтобы поддерживать другие кнопки на пульте, которые упрощают навигацию, придется прочитать документацию из SDK и писать JavaScript специфичный для конретного устройства — key codes разные.
И это только если начать рассматривать телевизоры. Со смартфонами и планшетами также много интересного, но это более распространенная и часто обсуждаемая тема.
Стоит начать работать в этом направлении и очень быстро встает вопрос о том, что версии сайтов для десктопов, мобильных устройств и телевизоров должны быть различными. И различаться должны не только во View. Должны быть разные модели, а значит лучше всего, когда с ними работают разные методы контроллеров.
Понятно, что самое простое — сразу сделать разные сайты для разных устройств и редиректить на нужный. Откинем такое решение как слишком простое. К этому варианту можно откатиться в любой момент.
Можно конечно делать для разных устройств разные методы в одном и том же контроллере, но хотелось бы более удобного и красивого решения.
Учитывая архитектуру ASP.NET MVC 4, есть только один подходящий вариант. Внутри MVC приложения (проекта), каждый из вариантов сайта должен быть выполнен в своей Area. По User Agent String мы может определить от какого устройства/браузера поступает запрос и направить его в нужную Area.
Чтобы переправить в нужную Area нужно для кажого маршрута (Route) в таблице рутинга добавить ограничение (Constraint).
Минус такого подхода в том, что такое ограничение нужно не забыть добавить во все маршруты.
Например, если мы сделали Area в которую нужно перенаправлять всех с Chrome browser, то Area Registration будет выглядеть так:
public class ChromeAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "Chrome"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Chrome_default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { isChromeBrowser = new IsChromeConstraint() }
);
}
}
При этом ограничение будет выглядеть так:
public class IsChromeConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
string userAgent = httpContext.Request.UserAgent;
if (string.IsNullOrWhiteSpace(userAgent)) { return false; }
return userAgent.Contains("Chrome");
}
}
При этом у нас есть основная Area, куда должны направляться все остальные браузеры, кроме Хрома.
public class DesktopAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "Desktop"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Desktop_default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { isNotChromeBrowser = new IsNotChromeConstraint() }
);
}
}
в ней мы также должны использовать ограничение, которое фильтрует браузеры отсекая Хром:
public class IsNotChromeConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
string userAgent = httpContext.Request.UserAgent;
if (string.IsNullOrWhiteSpace(userAgent)) { return false; }
return !userAgent.Contains("Chrome");
}
}
Выставлять ограничения для всех маршрутов во всех Area необходимо, несмотря на то, что маршруты в рантайме просматриваются сверху вниз. Дело в том, что порядок регистрации AreaRegistration при старте случайный. Этого можно избежать, если регистрировать маршруты всех Area в одном месте — в Global.asax — явно указывая их порядок. Тогда можно гарантировать, что проверка на Хром браузер всегда будет происходить первой.
Если Вам это надоест, вы всегда можете легко вынести каждую Area в отдельное приложение и хостить на разных доменах.
Автор: shirmanov
Источник [1]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/net/23089
Ссылки в тексте:
[1] Источник: http://habrahabr.ru/post/163225/
Нажмите здесь для печати.