Category Archives: ASP.NET

ASP.NET Device Filters

Nedávno se mi připomněla jedna starší lahůdka (čti obskurnost, za kterou může ten zpropadený svět heterogenních browserů) – Device Filters. Dovolím si tedy připomenout:

Jde o víceméně elegantní deklaratorní zápis, jak nastavovat různé hodnoty jednotlivých properties controlů a direktiv v ASP.NET v závislosti na browseru. Syntaxe je jednoduchá:

<asp:Label IE:Text="Používáte Internet Explorer" Mozilla:Text="Používáte Firefox" PIE:Text="Používáte Pocket IE" Text="Používáte Buchvíco" runat="server" />

Není to jen o properties controlů, dá se to použít i pro direktivy, takže například pro <%@ Page %> lze nastavit MasterPageFile či Theme. Rozpoznávané browsery se řídí browser-definition-files (App_Browsers, browserCaps).

ASP.NET Sprite and Image Optimization Framework

Že Microsoft ASP.NET team si už delší dobu hraje s věcmi kolem CSS Sprites se vědělo už dlouho. Nakonec nečekají na další release ASP.NET a uvolnili svůj ASP.NET Sprite and Image Optimization Framework už nyní (na Codeplex). Pokud tedy chcete na svých webech optimalizovat rychlost načítání a zobrazování obrázků, určitě doporučuji Vaší pozornosti. Kdo netušíte, o co jde, potom viz instruktážní video (ve zkratce jde o slučování několika obrázků do jednoho a zobrazování výřezů z něj na Vaší webové stránce pomocí CSS stylování s background-image).

XmlDataSource – pozor na jeho cachování při nastavování property Data

XmlDataSource má poměrně předurčený scénář použití a dokáže velmi nemile překvapit, pokud zapojíte vlastní fantazii a v dobré víře ho použijete jinak (ač zdravý člověk by očekával, že to fungovat bude). Tak především:

  • vlastnost EnableCaching je defaultně nastavena na true (což není úplně očekávané, ale budiž, dokumentované),
  • Cache je však poměrně zákeřná a ne vždy reflektuje vaše změny, vše se odvíjí od implementace metod GetXmlDocument() a  CreateCacheKey(), z nichž lze vyčíst, co všechno považuje XmlDataSource za změnu situace vyžadující reload dat a co ne.
  • tak například změna hodnoty property Data (zápis nového XML stringu) změnou pro Cache není a XmlDataSource vesele vrací stále původní XML až do vypršení Cache!
  • za změnu se považuje zejména změna v hodnotě DataFile nebo TransformFile, dále pak změna souboru, na který se DataFile nebo TransformFile odkazují,
  • XmlDataSource je tedy předurčeno pro použití právě přímo s XML soubory uloženými na disku, na které se odkazujete pomocí DataFile a TransformFile, zatímco přímé nastavování property Data je poněkud nedotažený scénář (i když přípustný).

…z čehož se pro mě jen potvrzuje, že datasources (CokolivDataSource) jsou cesta do pekel. :-)

web.config transformace a Code Contracts – Dema [MS DevDays 2009]

Dema k mým ukázkám na konferenci MS DevDays 2009:

Záznam z vystoupení nebyl pořizován, na téma web.config transformací však doporučuji svůj screencast.

Pozor na IIS Application pool: Maximum Worker Processes (Web Garden)

V nastavení application poolu na IIS je zastrčeno jedno nastavení s výchozí hodnotou 1, které je poměrně zrádné, pokud ho někdo změní a neví, co to přesně znamená.

Jde o volbu „Maximum Worker Processes“ a neznalé svádí tuto hodnotu z jedničky zvětšit na vyšší číslo.

Co to však ve skutečnosti znamená – jde o to, že IIS pustí pro Application Pool více instancí Worker Processu (w3wp.exe), které jsou navzájem izolované. Vznikne tak více nezávislých instancí aplikací běžících na daném Application Poolu a celé se to začne chovat jako Web Garden (= lokální virtuální Web Farm na jednom serveru). Následky jsou pak prakticky stejné, jako běh aplikace na webové famě – instance aplikace mezi sebou nezdílí kontext (Application, Cache, in-proc Session, atp.).

Protože každý Váš request pak může vyřdit jiná instance aplikace, projevy mohou být např. následující:

  • ztrácí se Vám Session, pokud používáte výchozí InProc session (hodnoty Session jsou uloženy na jiném „serveru“, než který vyřizuje aktuální request),
  • nefunguje dobře cachování (každý „server“ si udržuje vlastní cache a musí se tedy naplnit tolik cachí, kolik „serverů“ Vám běží),
  • ztrácí se Vám hodnoty Application contextu (opět stejný důvod),
  • nefungují Vám grafy DevXpress (protože si obrázek ukládají do lokálního contextu v okamžiku renderování stránky s grafem a požadavek browseru na obrázek grafu se dostane na jiný „server“),
  • atp. atp.

Osobně v běžném provozu nenacházím scénář, kde by Maximum Worker Processes mělo být nastaveno jinak než na 1. Dokážu si představit jedině, že někdo chce záměrně testovat chování své aplikace na webové farmě, nebo nějaké obskurní důvody s unmanaged componentami, nebo řešením nedostatečné thread-safety aplikace.

ASP.NET Routing – Když v IIS7 integrated-mode nechodí Session

Pokud Vám po nastavení ASP.NET routingu na IIS7 v integrated-mode nechodí na stránkách Session, pak je potřeba elementu system.webServer/modules nastavit atribut runAllManagedModulesForAllRequests na true:

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true"><!-- bez tohoto s ASP.NET Routingem nechodí Session v integrated-mode -->
        <remove name="UrlRoutingModule" />
        <add name="UrlRoutingModule"
             type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    </modules>

…ono to není jenom o Session, pro ASP.NET Routing se v integrated-mode nespouští moduly, které mají pre-condition managedHandler.

„Could not load file or assembly System.Web.Extensions“ při načítání controlů metodou LoadControl

Na zajímavý problém jsem narazil při implementaci použití CMS a našeho prezentačního frameworku. Obojí je kompilováno pro .NET 2.0, používáme je s .NET Frameworkem 3.5.
CMS načítá *.ascx standardní metodou:

Page.LoadControl("~/Test.ascx");

Bohužel se objevil problém s načítáním assembly, které jsou ve web.configu redirectovány na nové verze:

 

Could not load file or assembly 'System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. Systém nemůže nalézt uvedený soubor. 
<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
            <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/>
            <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
        </dependentAssembly>
        <dependentAssembly>
            <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/>
            <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
        </dependentAssembly>
    </assemblyBinding>
</runtime>

Příčina a řešení problému byla taková, že jsem v konfiguračním souboru musel odstranit namespace (atribut xmlns) z elementu configuration.

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">

asp:Chart aneb grafy od Microsoftu

Microsoft přišel se svým „vlastním“ controlem na renderování grafů do webových stránek (ve skutečnosti je to zřejmě Dundas „Lite“).

<asp:Chart runat="server"/>

Každopádně je to zajímavá alternativa ke komerčním komponentám třetích stran a přestože podstatně chybí design-time podpora, určitě se na nové grafy podívám.
Control, dokumentace i rozsáhlá dema jsou ke stažení.
Krátké intro-video můžete zkouknout i na MSTV.cz.

Pozor na ImageUrl, resp. UrlPathEncode() a znaky % (procenta) nebo # (hash)

Při bezstarostném používání Image.ImageUrl jsem narazil na zajímavý problém – pokud se Vám v názvu souboru nebo v cestě k němu vyskytne % (procenta) nebo # (hash), pak máte problém – metoda HttpUtility.UrlPathEncode(), kterou Image.ImageUrl a mnohé další controly pro encodování URL odkazů používají, Vám tyto znaky neencoduje:

<asp:Image ImageUrl="~/Folder #3/File.jpg" runat="server" />

udělá

<img src="/Folder%20#3/File.jpg" />

protože

HttpUtility.UrlPathEncode("/Folder #3/File.jpg") == "/Folder%20#3/File.jpg"

Metoda UrlPathEncode() totiž encoduje jen mezerník a non-ASCII znaky.

Správné samozřejmě je, abyste se na webových serverech pokusili těmto znakům vyhnout. Nicméně uživatelé jsou tvořiví a tak se můžete dočkat překvapení stejně jako já.

Osobně si myslím, že se jedná o bug v metodě UrlPathEncode(), resp. o nenaplnění očekávaného contractu, nicméně Microsoft to samozřejmě interpretuje jako by-design a radí, ať si uděláte Replace() těchto znaků sami.

Nezbývá tedy než:

myImage.ImageUrl = path.Replace("%", "%25").Replace("#", "%23");

Mimochodem obdobných vychytávek se můžete dočkat i se znakem + (plus).

web.config transformace – Screencast, slides, dema [MSTV 2009]

Screencast, který jsem svého času vytvořil pro MSTV.cz

Slides a dema ke screencastu:

Viz též: