2008. július havi bejegyzések

Számok a felhőről

Nacsa Sándor blogjában olvastam az SQL Server Data Servicesről, ami lényegében egy a “felhőben” elérhető adatközpont szolgáltatás. Az alapja természetesen SQL Server és úgy valósították meg, hogy világszerte garantálja a szükséges megbízhatóságot és rendelkezésre állást. Ilyenkor persze felmerül az emberben, hogy milyen infrastruktúra is van a háttérben?

Találtam néhány korábbi adatot:

A Microsoft 300.000 szerverből álló konténer farmot épít Chicagoban. A tervek szerint ez a szám havonta 20.000 (!) szerverrel fog nőni. Próbáljuk belőni a nagyságrendet! A Facebook most 10.000 szerverrel üzemel. Tehát havonta 2 Facebook pluszban. A Google becslések szerint 450.000 szervert üzemeltetett 2006-ban világszerte.

Mindebből tisztán látszik, hogy olyan jövőben gondolkodnak, amelynek az alapjait a felhőben biztosított szolgáltatások jelentik. A Live Search, az MSN és a Windows Live még csak az első lépések, íme néhány szám ezekről (forrás: Bink):

MS online services stats

Érdekes feladat lehet ekkora számokra tervezni.

Reklámok

Autópálya információk SMS-ben

Biztos sokak által ismert, hogy az autópályákkal kapcsolatos aktuális információk SMS-ben is lekérdezhetőek. Én nem vagyok SMS rajongó, főként vezetés közben nem, ezért inkább készítettem egy Windows Mobile alkalmazást.

A protokoll nagyon egyszerű, SMS-t kell küldeni a +36 70 7774636 számra M0, M1, M3 vagy M7 tartalommal és általában 2 SMS-ben jön a válasz (valamikor később). Windows Mobile 5-től kezdve .NET Compact Framework segítségével könnyen megy az SMS küldés: a Microsoft.WindowsMobile.PocketOutlook névtérben lévő SmsMessage osztályt jól kitalálták:

    SmsMessage message = new SmsMessage();
    message.To.Add( new Recipient( this.txtPhoneNumber.Text ) );
    message.Body = speedwayName;
    message.RequestDeliveryReport = this.chkReceipt.Checked;
    message.Send();        

A felhasználói felület megalkotása mindig kényes egy mobil alkalmazás esetén, így elgondolkodtam azon, hogy hogyan akarom a válasz SMS-eket megjeleníteni. A Microsoft.WindowsMobile.PocketOutlook.MessageInterceptor osztály lehetőséget ad arra, hogy az alkalmazásom értesítést kapjon, ha beérkezik egy üzenet, de így az olvasást biztosító felhasználói felület megvalósítása az én feladatom maradna. Az alapértelmezett buborékos megjelenítéshez használt rendszerfont mérete szerencsére elég nagy ahhoz, hogy még vezetés közben is el tudjam olvasni. Ráadásul így bezárhatom az alkalmazást, visszatérhetek a GPS-hez, ami praktikus, hiszen a válaszok sokszor percekkel később jönnek.

A másik felhasználói felülettel kapcsolatos kérdés az volt, hogy hogyan akarom a kérést elküldeni. Egy desktop alkalmazásnál nem probléma, combo boxból kiválasztom, hogy melyik autópálya érdekel és egy gombra kattintva indul is az SMS. Vezetés közben viszont kizárt, hogy ezt meg tudjam tenni, így a bazi nagy gombos megvalósítást követtem, így nem kell stylus, elég az ujjam, bármilyen nagy is. Némi Mio-szerű fekete dizájnnal megspékelve ilyen lett a főablak:

SpeedwayInfo Main ablak

Mivel a telefonszám nem sűrűn változik, ezért a gyors megoldást választottam, bedrótoztam az alkalmazásba.

Probléma volt, hogy a sikeres vagy sikertelen SMS küldésről hogyan adok visszajelzést a felhasználónak (magamnak). Úgy döntöttem, hogy a hang a legkézenfekvőbb megoldás, mert ez vonja el legkevésbé a figyelmemet a vezetésről. Kerestem két WAV fájlt és erőforrásként beágyaztam a szerelvénybe, a tartalmukat pedig a Assembly.GetExecutingAssembly().GetManifestResourceStream( "SpeedwayInfo.Sounds.Ok.wav" ) metódus meghívásával kérdezem le. A stream lejátszásához nem találtam felügyelt osztályt, így kellett egy kis P/Invoke:

    [DllImport( "CoreDll.DLL", EntryPoint = "PlaySound", SetLastError = true )]
    private extern static int WCE_PlaySound( string szSound, IntPtr hMod, int flags );

    [DllImport( "CoreDll.DLL", EntryPoint = "PlaySound", SetLastError = true )]
    private extern static int WCE_PlaySoundBytes( byte[] szSound, IntPtr hMod, int flags );

Miután sikerült a streamet byte tömbbé alakítani, a lejátszás már csak egy sor:

    Sound.WCE_PlaySoundBytes( this._soundBytes, IntPtr.Zero, (int) ( Flags.SND_ASYNC | Flags.SND_MEMORY ) );

Íme néhány tanulság:

  • Mobil alkalmazás esetén a felhasználói felület kialakítása mindig kritikus. Desktop alkalmazásnál is, de itt még inkább.
  • A felhasználói felület kitalálása és megfelelő kialakítása gyakran több időt visz el, mint a kódolás.
  • Nem csak egér van a világon 🙂
  • A PocketOutlook névtér nagyon jól használható.
  • Compact Frameworkön is van P/Invoke, nem kell megijedni tőle.

Ha valakit érdekel, az alkalmazás letölthető, legalább Windows Mobile 5.0 és Compact Framework 3.5 kell neki.

Zermatt

Zermatt egy kisváros Svájc déli részén, mindössze tíz kilométerre az olasz határtól. A kb. 5500 fős település zsákfalu, 1620 méteres tengerszint feletti magasságban egy völgy végében, egy gleccser közelében fekszik. Érdekesség, hogy a tiszta levegő megóvása érdekében belső égésű motorokkal hajtott autók nem hajthatnak be a városba. Síparadicsom, csendes kisváros gyönyörű környezetben. Mi vezette a Microsoft fejlesztőit arra, hogy épp ezt a várost válasszák egy fejlesztői keretrendszer kódnevévé?

Talán mert mint minden határközeli svájci város, ez is a környező nemzetek, hagyományok olvasztótégelye. A “Zermatt” pedig egy új, Microsoft fejlesztésű developer identity framework kódneve.

A világban egyre inkább előtérbe kerül a hagyományos felhasználónév-jelszó pároson alapuló hitelesítési mechanizmusok leváltásának szükségessége. Az egyik lehetséges megoldás az ún. claims-based hitelesítés, amikor az alkalmazás tetszőleges információkat (claim) kérhet a felhasználótól és azok alapján határozza meg, hogy a felhasználónak mihez van joga és mihez nincs. (Na, ezt durván leegyszerűsítettem.) Ilyen hitelesítési mód például az MSDN Kompetencia Központ oldalán általunk is használt Windows CardSpace alapú bejelentkezés, amit egységesen ez az ikon jelez minden weblapon a világhálón:

CardSpace logo

Amikor ezt én annak idején megvalósítottam, gyakorlatilag semmilyen támogatás nem volt hozzá, minden vezérlőt, JavaScriptet egyedileg kellett megírnom. A tapasztalatokból itt cikksorozat is született (1, 2, 3, 4, 5), és nem én voltam egyedül a világon, aki nagyon várta, hogy a Microsoft keretrendszer szintű támogatást adjon a CardSpace alapú bejelentkezéshez ASP.NET alkalmazások esetére: vezérlőket és objektum modellt, ami végül egy standard IPrincipal objektumot ad eredményül anélkül, hogy mindenféle részlettel, például token összeállítással és titkosítással kellene közvetlenül foglalkoznunk.

Most mindez megtörtént, ez a keretrendszer a “Zermatt”, ráadásul nem csak ASP.NET alkalmazásokat támogat, hanem tetszőleges .NET-es alkalmazásban, például WCF környezetben is használható. Jelen pillanatban a keretrendszer nyilvános béta változata érhető el a Connect oldalon. További információkat Vittorio Bertocci blogbejegyzéséből tudhatunk meg, vagy aki a fejlesztői részletek iránt érdeklődik, annak Keith Brown whitepaperjét tudom ajánlani.

 

ASP.NET AJAX jövőkép

Korábban már írtam néhány olyan komponensről vagy szolgáltatásról, melyek a tervek szerint az ASP.NET AJAX részei lesznek. Nos, a jelek szerint mégsem 😦

Tavaly elkezdtem boncolgatni a Microsoft AJAX Library azon részeit, amik még nem a támogatott csomag részei, hanem csak az ASP.NET Futures csomagban érhetőek el. Ezek közül számomra két terület különösen kedves, a kliens oldali vezérlők és a kliens oldali deklaratív adatkötés. Akik esetleg nem látták az erről szóló előadást a tavalyi Web Konferencián:

  • A kliens oldali vezérlők JavaScriptben implementált osztályok, amik a szerver oldali vezérlőkhöz nagyon hasonlóan viselkednek. Létezik például Sys.Preview.UI.TextBox osztály, aminek van Text tulajdonsága, amit a get_Text és set_Text metódusokkal lehet kiolvasni. Elfedi az egész HTML DOM-ot és a böngészőfüggő részleteket, ráadásul a modell teljesen ismerős a .NET világból, csak a szintakszis JavaScriptes.
  • A kliens oldali adatkötés lehetővé teszi, hogy kliens oldali vezérlőket kapcsoljunk egymáshoz, vagy éppen adatokhoz, sőt mindezt deklaratívan XML-Script formátumban megtehetjük.

Legalábbis úgy volt, hogy majd egyszer megtehetjük. A konferencia idején még nagyon kezdetleges változatban volt mindez elérhető, alap funkciók működtek és az út világos volt, hogy merre haladunk. Mivel azonban sok hír nem látott nyilvánosságot ezeknek a funkcióknak a jövőjéről, bedobtam egy levelet a Microsoft Regional Director levlistára és hamarosan meg is jött Scott Guthrie válasza, majd pár nappal később az információk publikusan is megjelentek a CodePlexen. Érdemes elolvasni az ott közzétett ASP.NET AJAX Roadmap doksit, számos változást terveznek:

  • Ami szimpatikus, hogy a sokféle közzétételi formát egy kicsit gatyába rázzák, jobban követhető lesz, hogy mi minek a részeként érhető el és honnan, mi támogatott és mi nem. Ez jó.
  • Nagy hangsúlyt fordítanak a kliens oldali adatkezelésre, így a template alapú adatkötésre is. Ez is jó.
  • Sajnos nem vagyok kibékülve azzal a szintakszissal, amit majd el kell viselnünk. Íme egy példa, a feladat megérteni, hogy mit csinál (ennél van “szebb” is :)):

<div id=”repeater1”></div>

<div id=”template1” class=”sys-template”>
  <h2><a href=”{{ ‘products/’ + id }}”>{{name}}</a></h2>
  <p>{{description}}</p>
</div>

<script type=”text/javascript”>
  Sys.Application.add_initialize(function() {
  $create(Sys.UI.DataView, {
    template: $get(“template1”),
    data: myData
  }, {}, {}, $get(“repeater1”));
}
</script>

  • Sajnos számomra még mindig nem egyértelmű, hogy mindebből mikorra lesz valami és ez szomorít el legjobban 😦

A friss információk alapján úgy látom, hogy még jó darabig nem célszerű olyan projektet tervezni, amik ezekre a Futures funkciókra épülnek, ez most óriási változás. Az XML-Script támogatás a jelek szerint nem fog megszületni, bár ezt így nem láttam leírva (csak azt, hogy bonyolult és lassú). Persze ez még csak roadmap, aki szereti a bétázást, próbálja majd ki és írja meg a véleményét a fejlesztőknek!

 

Workflow Foundation – miért kellene, hogy érdekeljen?

Egyre gyakrabban találkozom azzal a kérdéssel, hogy mikor érdemes bevetni egy alkalmazás megvalósításához a Windows Workflow Foundationt és egyáltalán mi lesz jobb attól, ha egy aránylag komplex komponenssel bővítjük a rendszerünket?

Első ránézésre a WF bizony egy összetett, vízfejű szörnyetegnek tűnik, foglalkozni kell vele, mire az ember megérti, hogy melyik része mire jó. Egyszerű problémák megoldásához nagy overheadként látja az ember és nehéz átlátni, hogy egy konkrét esetben nyerünk-e vele vagy épp kockára tesszük a projekt sikerét azáltal, hogy egy újabb technológiát próbálunk összereszelni a többivel.

Tavaly volt szerencsém részt venni a barcelonai TechEd Developers konferencián, ahol az egyik szünetben ezekről a kérdésekről beszélgettem Matt Winklerrel, a WF csapat egyik szakértőjével. Mivel ezek a kérdések újra és újra előkerülnek, úgy döntöttem, hogy megosztom a videót:

Matt Winkler interjú

A videó első fele a Workflow Foundationről szól, a beszélgetés második felében pedig a .NET Framework 3.5 verziójában megjelent újdonságokról, elsősorban a WF és a Windows Communication Foundation integrációjáról kérdeztem Mattet. (Ez utóbbiról egyébként már volt ezen a blogon egy részletesebb cikk.)

A beszélgetés mindössze 10 perc, aki most kezd a témával foglalkozni, annak bevezetőként tudom ajánlani.

 

Saját activity SharePoint Designerbe

A SharePoint Designer workflow tervezőjével sok feladatot könnyen megoldhatunk, bonyolultabb esetekben azonban hamar kifuthatunk a funkciókból. Szerencsére a lista bővíthető, be lehet varrni saját activity-t az eszközbe.

Ehhez csak a következőket kell tennünk:

1. Készítsük el a szokásos módon a saját activity komponensünket egy Activity Library típusú projektben.

2. Lássuk el a szerelvényt erős névvel és telepítsük a központi szerelvénytárba (GAC).

3. Keressük meg a 12TEMPLATE1033WorkflowWSS.ACTIONS fájlt, készítünk róla másolatot akármi.ACTIONS néven (a kiterjesztés fontos) ugyanabba a mappába és egy Action elemben írjuk le az activity-nket. Például egy mappa másolását elvégző saját FolderCopyActivity így írható le:

    <?xml version="1.0" encoding="utf-8"?>
    <WorkflowInfo>
        <Actions Sequential="then" Parallel="and">
            <Action Name="Mappa másolása"
                ClassName="MyActivityLib.FolderCopyActivity"
                Assembly="MyActivityLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e1b2225a7cb586c4"
                Category="Saját"
                AppliesTo="all">
                <RuleDesigner Sentence="A %1 mappa másolása a %2 mappába">
                    <FieldBind Field="SourceFolder" Text="forrás" DesignerType="TextArea" Id="1" />
                    <FieldBind Field="TargetFolder" Text="cél" DesignerType="TextArea" Id="2" />
                </RuleDesigner>
                <Parameters>
                    <Parameter Name="SourceFolder" Type="System.String, mscorlib" Direction="In" />
                    <Parameter Name="TargetFolder" Type="System.String, mscorlib" Direction="In" />
                </Parameters>
            </Action>
        </Actions>
    </WorkflowInfo>

Érdemes megfigyelni, hogy a Sentence attribútumban egy értelmes mondatot kell megadnunk, ami meg fog jelenni a felhasználói felületen. A % jellel jelölt paraméterek megjelenését a FieldBind elemekben tudjuk részletezni és a Parameters elemben tudjuk azokat az Activity osztály dependency property-jeihez kapcsolni. Célszerű odafigyelni a DesignerType attribútumra, hogy olyat válasszunk, ami később megkönnyíti a paraméter beállítását. A lehetséges értékek listája az MSDN oldalain megtekinthető, ahogy az ACTIONS fájl teljes sémája is.

4. A webalkalmazásunkhoz tartozó web.config fájlban regisztráljuk a típust authorizedType-ként. Ez lényegében olyan, mint a SafeControl szekció, csak éppen a System.Workflow.ComponentModel.WorkflowCompiler elemben található:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <configuration>
        <!-- ... -->
        <System.Workflow.ComponentModel.WorkflowCompiler>
            <authorizedTypes>
                <!-- ... -->
                <authorizedType 
                    Assembly="MyActivityLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e1b2225a7cb586c4" 
                    Namespace="MyActivityLib" 
                    TypeName="*" 
                    Authorized="True" />
            </authorizedTypes>
        </System.Workflow.ComponentModel.WorkflowCompiler>
    </configuration>

5. Nyissunk rá a webhelyre SharePoint Designerben és frissítsük a nézetet, aminek hatására az eszköz letölti a szerverről az ACTIONS fájlt és meg fog jelenni az új activity-nk workflow tervezése közben.