Strßnky pro r∙znß za°φzenφ na jednΘ adrese v ASP.NET
S pomocφ rozÜφ°enφ .net Frameworku pro mobilnφ za°φzenφ m∙₧eme na n∞kolika °ßdcφch vytvo°it spolehliv² redirektor, kter² u₧ivatele p°esm∞ruje v₧dy na nejvhodn∞jÜφ verzi strßnek pro jeho za°φzenφ. Na rozdφl od podobnΘ funkce v PHP, o kterΘ jsme ji₧ psali, za nßs cel² mechanismus detekce typu a schopnostφ za°φzenφ toti₧ provede .net Framework sßm.
Je pot°eba si °φct, ₧e v∙bec nejde o jedin² zp∙sob, jak nabφzet jednu aplikaci pro vφcero za°φzenφ. DalÜφ mo₧nostφ m∙₧e b²t rozÜφ°enφ System.Web.UI.MobileControls.MobilePage. Zßkladnφ aplikace je pak v₧dy funkΦnφ vÜude i p°es urΦit² "spartßnsk² vzhled", viz nap°φklad Φlßnek Internetov² Φas prost°ednictvφm mobilu v ASP.NET. ╪eÜenφm je za°azenφ takzvan²ch DeviceSpecific Üablon, tak₧e lze pohodln∞ vytvo°it aplikaci, kterß se velmi flexibiln∞ p°izp∙sobuje mo₧nostem za°φzenφ.
P°edem m∙₧eme rovnou °φci, ₧e princip zde popisovanΘ aplikace je analogick² popisovanΘ aplikaci vyu₧φvajφcφ PHP. Zjistφme typ a schopnosti za°φzenφ a podle toho nastavφme URL pro nßslednΘ p°esm∞rovßnφ, Φφm₧ ·loha celΘ aplikace konΦφ. SystΘm .net Framework mß velmi komplexnφ rozÜφ°enφ pro mobilnφ za°φzenφ v prostoru nßzv∙ System.Web.Mobile
, dovede rozpoznat velkΘ mno₧stvφ za°φzenφ, a tak se k≤d aplikace scvrkne jen na zavedenφ pot°ebnΘho prostor∙ nßzv∙, zφskßnφ ·daj∙ o schopnostech za°φzenφ a rozhodovacφ Φßst switch
. Na zßv∞r si jeÜt∞ ukß₧eme, jak .net Framework "nauΦit" rozpoznat novΘ za°φzenφ, kterΘ sßm o sob∞ rozpoznat nedovede.
Vychßzφme z p°edpokladu, ₧e v²chozφ strßnka Default.aspx, kterß zajiÜ¥uje detekci a p°esm∞rovßnφ, bude v ko°eni serveru a na zßklad∞ detekce p°esm∞ruje u₧ivatele do jinΘho adresß°e nebo na jinou strßnku. K≤d aplikace je opravdu trivißlnφ, proto si jej rovnou popφÜeme (zdrojov² k≤d ukßzek):
<%@ Import Namespace="System.Web.Mobile" %>
<script RunAt="server">
void Page_Load (Object sender, EventArgs e)
{
MobileCapabilities currentCapabilities = (MobileCapabilities) Request.Browser;
String pageUrl = "http://server.cz/cms/";
if ((currentCapabilities.IsMobileDevice && !currentCapabilities.Crawler) || Request.UserAgent.IndexOf("Windows CE") > -1)
{
switch (currentCapabilities.PreferredRenderingType)
{
case "xhtml-basic":
pageUrl = "http://wap.server.cz/";
break;
case "xhtml-mp":
pageUrl = "http://wap.server.cz/";
break;
case "html32":
if (((currentCapabilities.ScreenCharactersWidth <= 32) || (currentCapabilities.Browser.ToLower() == "pocket pc") || (currentCapabilities.MobileDeviceModel.ToLower() == "pocket pc")) && !(currentCapabilities.Browser.ToLower() == "opera" && currentCapabilities.Frames))
pageUrl = "http://server.cz/pda/";
break;
case "chtml10":
pageUrl = "http://server.cz/pda/";
break;
case "wml12":
pageUrl = "http://wap.server.cz/";
break;
case "wml11":
pageUrl = "http://wap.server.cz/";
break;
default:
break;
}
}
Response.Buffer = true;
Response.ClearContent();
Response.StatusCode = 301;
Response.StatusDescription = "Moved Permanently";
Response.Redirect(pageUrl,true);
}
</script>
V direktivßch strßnky (Page) vidφme zablokovanΘ funkce pro udr₧ovßnφ stavov²ch informacφ, kterΘ jsou pro naÜi aplikaci zbyteΦnΘ a jen by ubφraly systΘmovΘ prost°edky serveru. Je zaveden pot°ebn² prostor nßzv∙ System.Web.Mobile
.
V²konnß Φßst sestßvß z obsluhy udßlosti Page_Load
, kterß nastane p°i zavßd∞nφ strßnky na serveru. Zde si ulo₧φme zφskanΘ schopnosti za°φzenφ (MobileCapabilities) z vlastnosti Request.Browser
. Dßle si nastavφme prom∞nnou udßvajφcφ °et∞zec URL, kam se bude p°esm∞rovßvat - v²chozφ hodnotu nastavφme na adresu naÜφ webovΘ strßnky, urΦenΘ pro b∞₧nΘ prohlφ₧eΦe osobnφch poΦφtaΦ∙. Z vlastnosti IsMobileDevice urΦφme, zda se jednß o mobilnφ za°φzenφ. Pokud ano, podle vlastnosti PreferredRenderingType rozhodneme, jakΘ schopnosti za°φzenφ mß.
Pokud za°φzenφ tvrdφ, ₧e umφ zobrazit HTML k≤d verze 3.2, jeÜt∞ navφc ov∞°φme, zda Üφ°ka displeje je v∞tÜφ ne₧ dvacet znak∙ nebo zda nejde o za°φzenφ typu Pocket PC. To zjistφme z vlastnosti Browser a u n∞kter²ch za°φzenφ p°φmo jako rozpoznan² model z vlastnosti MobileDeviceModel. Pokud za°φzenφ vyhovφ t∞mto podmφnkßm, nastavφme URL na specißlnφ verzi naÜich strßnek vhodnou pro tato za°φzenφ (nap°φklad poΦφtaΦ s mobilnφm telefonem typu MDA). Pokud podmφnkßm nevyhovuje, jde z°ejm∞ o za°φzenφ s dostateΦn∞ velk²m displejem a proto adresu pro p°esm∞rovßnφ m∞nit nebudeme - ponechßme v²chozφ a klient bude p°esm∞rovßn na b∞₧nou webovou verzi. Obdobn∞ potom rozhodneme o p°esm∞rovßnφ za°φzenφ, kterß podporujφ takzvanΘ compact HTML, WML verze 1.1 a verze 1.2. Zda budou adresy stejnΘ nebo rozdφlnΘ zßle₧φ na tom, kolik verzφ mßme p°ipraven²ch.
Oproti popisu v MSDN vracφ vlastnost PreferredRenderingType
navφc jeÜt∞ dv∞ novΘ hodnoty, xhtml-basic
a xhtml-mp
. Tyto se t²kajφ p°edevÜφm nov²ch mobilnφch telefon∙ - naÜe ukßzkovß aplikace je sice "poÜle" na tutΘ₧ verzi jako klasickΘ wapovΘ telefony, ka₧dopßdn∞ je pot°eba se zab²vat i t∞mito hodnotami. Pokud bychom je v aplikaci neoÜet°ili, budou u₧ivatelΘ takov²ch telefon∙ posφlßni na v²chozφ strßnku urΦenou pro desktopovΘ prohlφ₧eΦe.
ProblΘmem mobilnφch za°φzenφ je, ₧e ne vÜechna podporujφ cookies a pokud by je aplikace na za°φzenφ odeslala, m∙₧e dojφt k selhßnφ zobrazenφ. Bohu₧el tedy musφme vypnout pou₧φvßnφ cookies pro session. Rovn∞₧ tak je pot°eba, aby URL, kterou ASP.NET generuje v hlaviΦce pro p°esm∞rovßnφ, byla skuteΦn∞ absolutnφ, jak definuje norma RFC. Obojφ zajistφme nastavenφm v souboru Web.config. Nastavenφ chovßnφ mechanismu session je globßlnφ (nelze nastavit pro location nebo v pod°φzenΘm adresß°i), proto je lepÜφ, kdy₧ webovß verze strßnek bude umφst∞na v podadresß°i, pro kter² je vytvo°ena zvlßÜ¥ virtußlnφ aplikace, abychom zde mohli sessions vyu₧φvat se vÜφm komfortem vΦetn∞ cookies.
Pot°ebnΘ nastavenφ v konfiguraΦnφm souboru Web.config:
<configuration>
<system.web>
<sessionState cookieless="true" />
<httpRuntime useFullyQualifiedRedirectUrl="true" />
</system.web>
</configuration>
Pro zlepÜenφ p°enositelnosti aplikace by se hodilo URL jednotliv²ch verzφ p°ebφrat z vlastnφch hodnot v souboru Web.config jako ve v²Üe odkazovanΘm Φlßnku, v naÜem p°φkladu je URL uvedeno napevno p°φmo v k≤du aplikace pouze z d∙vodu nßzornosti a p°ehlednosti.
Pokud se stane, ₧e mßme za°φzenφ, kterΘ .net Framework nerozpoznß sprßvn∞, nenφ problΘm popsat jeho vlastnosti do zvlßÜtnφho konfiguraΦnφho souboru do sekce browserCaps. V naÜem p°φkladu nadefinujeme fiktivnφ za°φzenφ Interval MDA do souboru Interval.Mda.config:
<use var="HTTP_USER_AGENT" />
<filter>
<case match="Mozilla\/4\.0 \(compatible; MSIE 4\.01; Windows CE; PPC; 240x320\)">
browser = "Pocket IE"
cachesAllResponsesWithExpires = "False"
canInitiateVoiceCall = "True"
canRenderEmptySelects = "True"
canSendMail = "True"
cookies = "True"
hidesRightAlignedMultiselectScrollbars = "False"
inputType = "virtualKeyboard"
isColor = "True"
isMobileDevice="True"
javascript = "True"
maximumHrefLength = "1024"
maximumRenderedPageSize = "20000"
mobileDeviceManufacturer = "Interval.cz"
mobileDeviceModel = "Interval.cz MDA"
preferredImageMime = "image/jpeg"
preferredRenderingMime = "text/html"
preferredRenderingType = "html32"
rendersBreaksAfterHtmlLists = "True"
requiredMetaTagNameValue = "HandheldFriendly"
requiresAttributeColonSubstitution = "True"
requiresContentTypeMetaTag = "False"
requiresDBCSCharacter = "False"
requiresFullyQualifiedRedirectUrl = "False"
requiresHtmlAdaptiveErrorReporting = "False"
requiresLeadingPageBreak = "False"
requiresNoBreakInFormatting = "False"
requiresOutputOptimization = "False"
requiresPostRedirectionHandling = "False"
requiresUniqueFilePathSuffix = "False"
requiresUniqueHtmlCheckboxNames = "True"
screenBitDepth = "24"
screenCharactersHeight = "17"
screenCharactersWidth = "32"
screenPixelsHeight = "320"
screenPixelsWidth = "240"
supportsAccessKeyAttribute = "True"
supportsBodyColor = "True"
supportsBold = "True"
supportsCharacterEntityEncoding = "True"
supportsCss = "True"
supportsDivAlign = "True"
supportsDivNoWrap = "False"
supportsEmptyStringInCookieValue = "True"
supportsFontColor = "True"
supportsFontName = "True"
supportsFontSize = "True"
supportsImageSubmit = "True"
supportsIModeSymbols = "False"
supportsInputIStyle = "False"
supportsInputMode = "False"
supportsItalic = "True"
supportsJPhoneMultiMediaAttributes = "False"
supportsJPhoneSymbols = "False"
supportsQueryStringInFormAction = "True"
supportsRedirectWithCookie = "True"
supportsSelectMultiple = "True"
supportsUncheck = "True"
tables = "True"
type = "Pocket IE"
</case>
</filter>
</browserCaps>
Hodnoty jednotliv²ch vlastnostφ samoz°ejm∞ m∙₧eme stanovit ruΦn∞, pro usnadn∞nφ se vÜak hodφ pou₧φt online Device Profiler na strßnkßch ASP.NET. S jeho pomocφ snadno otestujete vlastnosti a mo₧nosti za°φzenφ a nakonec se vytvo°φ kompletnφ definice browserCaps
.
Zb²vß si jen ukßzat, jak dßme .net Frameworku vlastnosti naÜeho za°φzenφ na v∞domφ. Do ko°enovΘho souboru Web.config nebo do hlavnφho konfiguraΦnφho souboru Machine.config p°idejte nßsledujφcφ definici do sekce system.web
a p°ihrajte vytvo°en² definiΦnφ soubor:
<browserCaps>
<file src="Interval.Mda.config" />
</browserCaps>
</system.web>
Podobn²ch definicφ je, jak vidno, mo₧nΘ p°idat libovoln² poΦet - nicmΘn∞ se hodφ Φas od Φasu sledovat updaty, zda nenφ k dispozici update definic mobilnφch za°φzenφ, abychom vlastnφ definicφ nenosili d°φvφ do lesa.
Pozn. red.: Tento Φlßnek vyÜel poprvΘ 18. 9. 2003. P∙vodnφ verze Φlßnku a k n∞mu vedenΘ diskuse jsou vßm k dispozici v ZIP archivech.