Navigace

Hlavnφ menu

 

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):

<%@ Page Language="C#" EnableViewState="False" EnableSessionState="False" %>
<%@ 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:

<?xml version="1.0" encoding="utf-8" ?>
<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:

<browserCaps>
  <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:

<system.web>
  <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.

R∙₧iΦka, Pavel (21. 8. 2004)
odborn² redaktor Interval.cz