Monthly Archives: January 2008

SharePoint szerszámosláda

A héten volt szerencsém SharePoint programozói tanfolyamot tartani a NetAcademiánál, ahol szokás szerint terítékre került egy nagy rakás ingyenesen letölthető, többnyire MVP-k által készített eszköz, ami segítheti a WSS programozók életét. Íme a kedvenceim listája:

SharePoint Server 2007 SDK (Microsoft)

A WSS és MOSS-sal kapcsolatos fejlesztői információk hivatalos forrása. A 176 MB-os letöltött állomány kicsomagolása után az igazi érték a 35 MB-os WSS3SDK.chm fájl, ami a WSS MSDN-szerű súgójának tekinthető. Örülhetünk, mert van már benne nyelvi szűrés, aztán meg sírhatunk, mert minden oldalon egyesével kell beállítani, ha a VB szintakszis nem érdekel. Ezen kívül óvatosan a példakódok átemelésével, mert nagyon nem egyértelmű, hogy melyik vonatkozik WSS 2.0-ra és melyik 3.0-ra; és persze ne lepődjünk meg, ha üres oldalt, vagy dokumentálatlan metódust találnánk.

A korábban külön életet élő Enterprise Content Management (ECM) Start Kit és Workflow Developer Starter Kit for WSS 3.0 is az SDK részeként tölthető le, tehát aki SharePointos WF activity-ket keres, az SDK példái között nézzen körül.

Vélemény: a SharePoint csapat úgy látszik eddig még nem tudta behozni a dokumentálás terén lévő elmaradásait, ezért az SDK olyan amilyen, de nélkülözhetetlen.

Letöltés (lehet, hogy később más URL-en lesz elérhető az újabb verzió!)

Online verzió az MSDN-en

VSeWSS: Windows SharePoint Services 3.0 Tools: Visual Studio 2005 Extensions (Microsoft)

Ennek a csomagnak a telepítésével SharePointos project és item típusok jelennek meg a Studioban, az 1.0 verzióban például ezek:

  • List Definition
  • Field Control
  • Module
  • Content Type
  • Web Part
  • Team Site Definition
  • Blank Site Definition
  • List Definition

Az eszköz határozottan hiánypótló, kényelmes, hogy tud solution fájlt előállítani, és a debuggolást egybekötötték a telepítéssel, tehát egyetlen F5 után a frissen telepített kódunkat tesztelhetjük. Óriási probléma számomra, hogy csak VS 2005-öt támogat, 2008-at nem, ráadásul nagy csend van a következő verzióról.

A VSeWSS része a SharePoint Solution Generator (SPSolGen), amivel létező webhely vagy lista definíciót visszafejthetünk Visual Studio projektté.

Vélemény: célszerű kipróbálni, de csak annak javaslom a használatát, aki tudja, mi történik a háttérben.

Letöltés: 1.0 verzió, 1.1 CTP verzió

Induláshoz: Walkthrough, Projekt fájlok leírása

Cabinet SDK (Microsoft)

A SharePointra telepíthető solution fájlok valójában .CAB fájlok, melyek előállításához szükség van a Cabinet SDK-ban található MakeCAB.exe segédprogramra.

Vélemény: ha nem elég feature-be csomagolni a kódunkat, hanem solutiont kell előállítanunk, akkor bizony erre szükség lesz. A VSeWSS megkönnyítheti a használatát.

Letöltés | Leírás (KB 310618) | Walkthrough Studioban történő használatáról

Visual Studio 2005 extensions for .NET Framework 3.0 – Windows Workflow Foundation (Microsoft)

Ha VS 2005-ös fejlesztő környezetet alakítunk ki – például azért, mert a VSeWSS még nem támogatja a VS 2008-at – és workflow-t akarunk fejleszteni, akkor ez a csomag készíti fel a Studio WF projekt típus kezelésére.

Vigyázat, MSDN nincs benne, tehát WF témában nem találjuk meg az osztályokat és a cikkeket, azok ugyanis a Vista SDK-ba kerültek. VS 2008 esetén nincs ilyen probléma, ott az MSDN részét képezi a WF dokumentáció is.

Vélemény: kis méretű letöltés, gyors telepítés, nem zavar be a Studioba és pont ugyanazt tudja, mint a VS 2008-ba beépített változat.

Letöltés

Internet Explorer Developer Toolbar (Microsoft)

Webfejlesztőknek nem kell bemutatni ezt az Internet Explorer toolbarként települő eszközt, grafikai, design, arculati problémák megoldásához, CSS matatáshoz, master page készítéséhez óriási segítség.

Vélemény: Minden webfejlesztő gépén ott a helye.

Letöltés

Sysinternals DebugView (Microsoft)

Ez a Mark Russinovich által készített eszköz lehetővé teszi, hogy a System.Diagnostics.Debug osztály által a hibakeresési naplóba írt üzeneteket azonnal megtekinthessük. Ennek főként akkor van jelentősége, ha olyan kódot készítünk, amihez nincs felhasználói felület. Ilyen például egy Windows Service alkalmazás, egy webszolgáltatás vagy éppen egy SharePointos eseménykezelő. Ha írunk debug logot (illik), akkor folyamatosan nyomon követhetjük, hogyan fut a kódunk, ráadásul mindezt anélkül, hogy a VS debuggerét használnánk. Nem egyszer láttam már, hogy a DebugView segített megtalálni, hogy éles környezetben miért nem fut rendesen a fejlesztői gépen amúgy tökéletesen működő kód.

Vélemény: egyszerű, kis eszköz, megspórolhatjuk vele a debuggerben töltött idő egy részét.

Letöltés | Honlap

.NET Reflector (Lutz Roeder)

A .NET Reflectort egy felügyelt kódban dolgozó fejlesztőnek sem kell bemutatni, lefordított kódokat fejthetünk vissza vele. Sajnos szükség van rá WSS fejlesztéskor is, az SDK-ban lévő dokumentáció ugyanis még "kihívásokkal küzd". Sajnos időnként makacsul frissíteni akarja magát a netről, ami VPC-s környezetben nem mindig szerencsés.

Vélemény: legyen kéznél, szükség lesz rá.

Letöltés

SharePoint Explorer (Ontolica)

Számtalanszor fordul elő, hogy gyorsan meg kellene nézni egy SharePoint objektum valamelyik tulajdonságát, például egy lista ID-ját, egy mező belső nevét, vagy egy nézethez definiált query feltételt. A SharePoint Explorer segítségével lefúrhatunk az objektum modellben és láthatjuk az egyes elemek tulajdonságait, köztük számos olyat, ami sehol nem jelenik meg a felhasználói felületen. Nagyon sokat segít az objektum modell megértésében annak ellenére, hogy a felület nem frissül magától, időnként újra kell indítani, ha látni szeretnénk a változásokat.

Vélemény: egyetlen kis .exe, amivel beleláthatunk a WSS lelkivilágába. Ha objektum modellt programozunk, sokat segíthet.

Letöltés

SharePoint Explorer Client (DotNetFactory)

A SharePoint Explorer Client segítségével Internet Explorer add-in formájában láthatjuk a WSS webhelyünk tartalom hierarchiáját. Kényelmes, hogy fa nézetben látunk mindent, hogy közvetlenül ugorhatunk az egyes listákra, webhelyekre vagy oldalakra és praktikus, hogy a létrehozás menüpont is kéznél van. Úgy vettem észre, hogy belassítja az IE indulását.

Vélemény: végfelhasználóknak kiváló a tartalom szervezésének megértéséhez, programozóknak jobb az Ontolica féle SharePoint Explorer.

Letöltés

U2U CAML Query Builder (Karine "The CAML Girl" Bosch, U2U)

Nem szeretünk kézzel CAML-t írni, még akkor sem, ha nincs benne HTML és szkript, csak XML, például egy nézet vagy lekérdezés query-jében. Ekkor jöhet jól ez az eszköz, amivel összekattintgathatjuk a CAML formátumú lekérdezést, amit azután csak be kell másolni a kódunkba. A 2.1.0.0 különálló Windows alkalmazás, a 3.0 már SharePoint feature-ként települ és újabb menüpontok és oldalak formájában érhető el. Úgy vettem észre, hogy a Windows alkalmazás felhasználói felülete nagyon nem bolondálló, de többet tud, mint a beépülő változat. A webes verzió felhasználói felülete szebb, de lényegesen lassabb.

Vélemény: segít nem megutálni a CAML-t, játszunk vele egy kicsit.

Letöltés | Leírás | Walkthrough

SharePoint CAML Viewer (Renaud "Stramit" Comte)

Az SPCamlViewer segítségével meglévő CAML-t fejthetünk vissza és másolhatunk át saját kódunkba. Például a WSS webes felületén összekattintgatunk egy nézetet, majd a hozzá tartozó query definíciót átmásoljuk egy SPQuery objektum Query tulajdonságába. Hasznos, hogy látjuk az összes mező adatait, a lista és a nézet ID-ját, sőt akár C# kódot is tud közvetlenül előállítani.

Vélemény: aki építés helyett a visszafejtést választja, annak hasznos lehet.

Letöltés | Honlap

SharePoint Feature Manager (Todd S. Baginski)

Ahogy Windows alkalmazásainkhoz Windows Installer telepítőt vár tőlünk mindenki, úgy SharePoint kódunkat feature-be illik csomagolni. A feature telepítése, aktiválása, inaktiválása és eltávolítása legegyszerűbben az stsadm.exe paraméterezésével oldható meg. Ezeknek a parancssori utasításoknak az előállításához és futtatásához nyújthat segítséget Todd Baginski egyszerű Windows alkalmazása.

Vélemény: használhatjuk, ha nem írunk gyakran feature-t, egyébként úgyis lesz install.cmd és uninstall.cmd fájlunk, amit bekonfigurálunk a Studioban post build actionként.

Letöltés

SmartPart (Jan Tielens, U2U)

Aki hiányolja a designer támogatást a Studioból SharePoint webkijelzők fejlesztésekor, annak pont a SmartPartra van szüksége. Ez "Az év webkijelzője" díjat többször elnyert komponens lehetővé teszi, hogy Web User Control, azaz .ASCX fájl formájában készítsük el a kijelzőnket. Hátránya némi többlet telepítés és konfiguráció, de ha bonyolult felhasználói felületet kell készítenünk, akkor rengeteg időt spórolhatunk meg azzal, hogy a Toolboxról behúzogatjuk a vezérlőket és nem a CreateChildControls metódusban példányosítjuk és állítgatjuk be őket.

Sajnos a projekt a halálra ítélt GotDotNeten van egyelőre, és nagyon oda kell figyelni, hogy melyik verziót töltjük le.

Vélemény: feltétlenül próbáljuk ki, mielőtt nekiállunk karakterenként UI-t generálni.

Leírás | Letöltés | Walkthrough

CTExplorer: Content Type Explorer (Reiner Ganser)

A CTExplorer segítségével meglévő tartalom típusaink tulajdonságait tekinthetjük meg egy egyszerű Windows alkalmazásban. A tulajdonságok megtekintésén túl az igazi durranás ebben az eszközben, hogy képes a tartalom típusok feature-ként történő exportálására. Tehát ha szeretnénk egy új tartalom típust létrehozni, akkor exportálunk egy már létezőt és módosítjuk benne, amit szükséges.

Vélemény: saját tartalom típus kezeléséhez egyszerű kis kütyü. Ne várjunk tőle sokat, csak kezdőrúgást saját feature-ünk fejlesztéséhez.

Leírás (németül) | Letöltés

SPMasterPicker: SharePoint Master Page Picker (Renaud "Stramit" Comte)

Azoknak jöhet jól ez az eszköz, akik saját mesterlapot fejlesztenek WSS alá és hiányolják a webes felületről azt az opciót, hogy hozzárendeljék új mesterüket egy webhely gyűjteményhez. Az SPMasterPicker solutionként/feature-ként települ és a Site Settings oldalon jelenít meg egy Select a Master Page opciót, amire kattintva a Master Page Gallery-ből választhatunk magunknak mester oldalt.

Vélemény: akik mesterlapot fejlesztenek, azok valószínűleg nem akarják a hozzárendelést lekódolni, nekik jól jöhet.

Honlap | Letöltés

STSDEV: Simple Tools for SharePoint 2007 Development  (Ted Pattison)

Ez a nemrég megjelent grafikus felhasználói felülettel ellátott parancssori eszköz Visual Studio projektek generálására képes. Azon túlmenően, hogy előállít számunkra egy teljes projektet, beépül a fordítási folyamatba is, így a forráskód újrafordításakor egy teljes SharePointos solution áll elő. Mi több, a Build parancs kiadásával egy kattintással telepíthetjük is az elkészült solutiont. Érdekes kezdeményezésnek tűnik, a SharePoint Solution Package (.wsp) és a szükséges .ddf fájl automatikus előállítása határozottan szimpatikus. Első tájékozódáshoz a screencastokat érdemes megnézni.

Vélemény: úgy látom, jó úton indult el ez a projekt, de még nincs túl sok tapasztalatom vele, nagyon friss.

Honlap | Letöltés (kód és screencast)

Egyéb hasznosnak tűnő eszközök

Ezekkel nincs sok tapasztalatom, de így meglesz minden egy helyen:

SharePoint Cross-Site Configurator

Az SPConfigurator célja, hogy egyszerűsítse sok site collection átkonfigurálását azzal, hogy mindent egy lépésben tehetünk meg. Honlap | Letöltés

LINQ to SharePoint

Egyedi LINQ query provider, ami lehetővé teszi a SharePoint adatbázisában található adatok lekérdezését LINQ szintakszissal. Még igencsak alpha verzió. Honlap | Letöltés

CAML.NET

John Holliday projektje CAML lekérdezések összerakására .NET-es szintakszissal. Honlap | Letöltés

Referencia oldalak

Néhány oldal az SDK-ból, amire gyakran van szükség:

 

Workflow Services .NET 3.5-ben: SendActivity és ReceiveActivity

Ha valaki alaposan körülnéz a .NET Framework 3.5-ben workflow újdonságok után kutatva, aligha talál túl sok mindent. Mindössze két új activity van, a Send és a Receive activity-k, melyek azonban nagyon hasznosak, hiszen a korábban már annyit szidott ExternalDataExchangeService használatát tehetik feleslegessé. Előnyük, hogy a Windows Communication Foundationre épülnek, tehát ha tudunk WCF-ül, akkor nem fog gondot okozni a használatuk és valóban egyszerűbb lesz az életünk, mint az EDES alapú kommunikációval. Ugyanez a hátrányuk is, tudnunk kell WCF-ül, ha használni akarjuk őket, és így már nem csak a WF-hez, de a WCF-hez is értenünk kell; két, önmagában sem kicsi és egyszerű technológiában kell otthon lennünk.

Nézzünk egy egyszerű (??) példát a két új activity használatára.

WCF szolgáltatás készítése

Létrehoztam egy új WCF Service Library típusú projektet MyServiceLib néven, majd miután kitakarítottam belőle a generált kódot, definiáltam egy ICalcService nevű WCF szolgáltatás interfészt (tipp: Add New Item – WCF Service), még pedig így:

    namespace MyServiceLib
    {
        [ServiceContract]
        public interface ICalcService
        {
            [OperationContract]
            int Add( int first, int second );
        }
    }

A felhasznált attribútumok a WCF névterében, a System.ServiceModel névtérben találhatóak.

Az interfészt természetesen implementáltam is egy CalcService nevű osztályban, elég lényegre törően:

    public class CalcService : ICalcService
    {
        public int Add( int first, int second )
        {
            Console.WriteLine( "CalcService.Add( {0}, {1} )", first, second );
            return first + second;
        }
    }

Nincs az a WCF alkalmazás, amihez ne kellene konfig fájlt matatni, így hát elővettem a generált app.config fájlt és kigyomláltam belőle a Service1 nyomait a system.servicemodel szekcióban. Végül ez maradt:

    <system.serviceModel>
      <services>
        <service name="MyServiceLib.CalcService" behaviorConfiguration="MyServiceLib.CalcServiceBehavior">
          <host>
            <baseAddresses>
              <add baseAddress = "http://localhost:9091/CalcService/" />
            </baseAddresses>
          </host>
          <endpoint address="" binding="wsHttpBinding" contract="MyServiceLib.ICalcService" />
          <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
      </services>

      <behaviors>
        <serviceBehaviors>
          <behavior name="MyServiceLib.CalcServiceBehavior">
            <serviceMetadata httpGetEnabled="True"/>
          </behavior>
        </serviceBehaviors>
      </behaviors>
    </system.serviceModel>

Defeiniáltam tehát két endpointot, egyet a szolgáltatás meghívásához, egyet pedig a szolgáltatás leírásának lekérdezéséhez. Jegyezzük meg, hogy a 9091-es porton figyel a szolgáltatás. A Visual Studio 2008 egyik újdonsága, hogy bár ez egy library típusú projekt, mégis elindíthatjuk: létezik ugyanis egy WCF Service Host és egy WCF Test Client alkalmazás, amit elindít a Studio és abban azonnal tesztelhetjük a szolgáltatásunkat anélkül, hogy hoszt alkalmazást készítenénk hozzá.

Megjegyzés: normális esetben ezek hibát fognak jelezni, ugyanis az URL névterek matatása csak rendszergazdáknak engedélyezett és ugyebár nem vagyunk rendszergazdák a gépünkön. Vagy olvassuk el a hibaüzenetben hivatkozott idevágó MSDN cikket, vagy "Végre!" felkiáltással/anyázva/sajnálkozva/siránkozva indítsuk el a Studiot adminként.

Ha sikerrel jártunk, működni fog a szolgáltatásunk a teszt kliensben:

WCF Test Client

WCF hoszt alkalmazás készítése

Mi azért ne elégedjünk meg ennyivel, készítsünk egy saját konzolos hoszt alkalmazást MyServiceHost néven. A VS által generált konzol projekthez adjunk referenciát a szolgáltatás projektünkre és a System.ServiceModel szerelvényre. Ebben a szerelvényben, és egyben névtérben található a hosztolásért felelős ServiceHost osztály.

A hosztolás lényegében a ServiceHost példányosításából és az Open metódus meghívásából áll:

    static void Main( string[] args )
    {
        ServiceHost host = new ServiceHost( typeof( MyServiceLib.CalcService ) );
        host.Open();
        Console.WriteLine( "Service host fut..." );
        Console.ReadLine();
        host.Close();
    }

Most jön a dolog neheze, ugyanis a szolgáltatás meghívásához szükséges paraméterek konfig fájlból jönnek. A lényeg az endpoint, amiben három dolgot kell definiálnunk: address, binding, contract, a WCF ABC-je.

Szerencsés helyzetben vagyunk, a library projektnél már mindezt bekonfiguráltuk, másoljuk át azt az app.configot a konzol projekthez, ugyanis a .NET még mindig nem támogatja DLL-ek esetén a konfig fájlok használatát.

Ezek után a MyServiceHost projektnek gond nélkül fordulnia és futnia kell. Miközben fut, böngészőben megnézhetjük, mi látszik a http://localhost:9091/CalcService/ címen. Itt azonban meghívni nem tudjuk, klienst kell tehát készítenünk.

WCF kliens készítése

A kliens is egy konzol alkalmazás legyen, MyClient néven. Ha fut a service, akkor a Solution Explorerben a jobb gombbal kattintva találhatunk egy Add Service Reference menüpontot:

 Add Service Reference

A megjelenő ablakban a Discover gombra kattintva a Studio könnyen megtalálja a solutionben lévő szolgáltatásokat. Az ablak alján megadhatjuk, hogy az eszköz a MyServices névtérbe generálja a proxy osztályokat.

Egy using MyClient.MyServices; sor után, már bátran meghívhatjuk a szolgáltatásunkat a webszolgáltatásoknál már megszokott egyszerűséggel:

    Console.WriteLine( "Kliens elindult..." );
    CalcServiceClient service = new CalcServiceClient();
    Console.WriteLine( "Eredmény: {0}", service.Add( 5, 6 ) );
    Console.ReadLine();

Ha mindent jól csináltunk, akkor a varázsló generált nekünk egy nagy halom XML-t az app.config fájlba, ez alapján tudja a proxy, hogy hol van a szolgáltatás és hogyan kell meghívni. Le legyünk restek kitakarítani a szemetet, ennyi csak a lényeg, megint csak az ABC:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <system.serviceModel>
            <client>
                <endpoint
                        address="http://localhost:9091/CalcService/"
                        binding="wsHttpBinding"
                        contract="MyServices.ICalcService" />
            </client>
        </system.serviceModel>
    </configuration>

Hol van ebben a workflow?

Eddig tehát készítettünk egy egyszerű WCF szolgáltatást, hozzá hoszt alkalmazást és klienst. Hol van itt a Workflow Foundation szerepe?

A WF tipikusan akkor jöhet a képbe, ha hosszú ideig futó üzleti logikánk van, amit távolról szeretnénk elérni. A "hosszú ideig fut" feltételnek a WF, a "távolról elérni" feltételnek pedig a WCF örül. A kettőt egy processzben használni persze nem triviális, itt sem készítünk bonyolult példát, csak ugyanezt a számológépet workflow alapokon.

Workflow készítése ReceiveActivity használatával

Adjunk a solutionünkhöz egy Sequential Workflow Service Library típusú projektet MyWorkflowLib néven. Töröljük ki a Workflow1 és IWorkflow1 fájlokat és helyettük adjunk hozzá a projekthez egy szekvenciális workflowt CalcWorkflow néven. Ebben a workflowban a korábbiakhoz hasonlóan egy összeadást fogunk megvalósítani, ezúttal workflowval.

A Toolbox Windows Workflow v3.5 csoportjában találjuk a ReceiveActivity-t, húzzuk rá a folyamatra design nézetben. Ez az activity képes arra, hogy egy workflow-t WCF szolgáltatásként publikáljon a külvilág felé. Ehhez természetesen szükség van egy kommunikációs interfészre, a contractra.

Két módon járhatunk el:

  • Contract first: már megvan a kommunikációs interfész definíciója, ezt használjuk fel.
  • Workflow first: előbb megépítjük a folyamatot és közben definiáljuk a kommunikációs interfészt.

Mivel mi pont ugyanolyan logikájú folyamatot szeretnénk építeni, mint korábban a CalcService esetén, ezért a contract first utat választjuk és felhasználjuk a korábban létrehozott ICalcService interfészt. De csak az interfészt, a CalcService osztályt nem, hiszen pont azt váltjuk ki egy workflow-val. Az interfész azonos, de azúttal nem egy egyszerű osztály, hanem egy workflow implementálja. Hogy el tudjuk érni az interfészt, adjunk referenciát a MyServiceLib projektre.

A feldobott ReceiveActivity tulajdonság lapján állítsuk a CanCreateInstance tulajdonságot true értékre, jelezvén, hogy a hoszt alkalmazás létrehozhat egy új workflow példányt, ha ilyen (ezt később definiáljuk) üzenet érkezik. A contractot a ServiceOperationInfo tulajdonságnál definiálhatjuk:

ServiceOperationInfo tulajdonság beállítása

Az Add Contract gombra kattintva itt építhetnénk meg a kommunikációs interfészt (workflow first), helyette inkább kattintsunk az Import gombra és válasszuk ki a MyServiceLib projektből az ICalcService interfészt (contract first).

Definiáljunk a CalcWorkflow osztályban tulajdonságokat a bemeneti paraméterek és az eredmény tárolására:

    public int First { get; set; }
    public int Second { get; set; }
    public int Result { get; set; }

Az így létrehozott változókat köthetjük a ReceiveActivity tulajdonságlapján az Add metódus paramétereihez és visszatérési értékéhez:

A ReceiveActivity beállításai 

A ReceiveActivity-be tegyünk egy CodeActivity-t, nevezzük add-nak és írjuk meg a "nagy bonyolultságú" és "hosszú ideig futó" üzleti logikánkat:

    private void add_ExecuteCode( object sender, EventArgs e )
    {
      Console.WriteLine( "CalcWorkflow.add_ExecuteCode: First={0}, Second={1}", First, Second );
      this.Result = this.First + this.Second;
    }

Workflow hoszt készítése

Elkészültünk a folyamattal, amit persze valahol hosztolni kell. Nem használhatjuk a korábbi hoszt kódunkat, hiszen az közvetlenül hosztolta a WCF szolgáltatásunkat, most pedig egy workflowt és ezzel az egész workflow runtime-ot kell hosztolnunk.

Legyen ez is egyszerű konzol alkalmazás, MyWorkflowHost néven, és adjuk hozzá a szükséges szerelvény referenciákat: kell a System.Workflow.*, ahogy azt már WF 3.0-ban megszoktuk, de mell még a System.ServiceModel és – itt a lényeg – a System.WorkflowServices is. Természetesen szükség lesz a MyWorkflowLibre is.

A hosztoláshoz ezúttal nem a korábban megszokott WorkflowRuntime vagy ServiceHost osztályt, hanem egy új, WCF-WF specifikus WorkflowServiceHost osztályt használunk. Ezt kell megpéldányosítani és meghívni rajta az Open metódust. Ha fel akarunk iratkozni a WorkflowRuntime eseményeire, akkor kicsit trükközni kell, ezért álljon itt a teljes kód:

    static void Main( string[] args )
    {
      WorkflowServiceHost host = new WorkflowServiceHost( typeof( MyWorkflowLib.CalcWorkflow ) );

      WorkflowRuntime runtime = 
        host.Description.Behaviors.Find<WorkflowRuntimeBehavior>().WorkflowRuntime;

      runtime.WorkflowCreated += delegate( object sender, WorkflowEventArgs e ) 
        { Console.WriteLine( "WorkflowCreated: t{0}", e.WorkflowInstance.InstanceId ); };
      runtime.WorkflowTerminated += delegate( object sender, WorkflowTerminatedEventArgs e ) 
        { Console.WriteLine( "WorkflowTerminated: t{0}", e.Exception.Message ); };
      runtime.WorkflowCompleted += delegate( object sender, WorkflowCompletedEventArgs e ) 
        { Console.WriteLine( "WorkflowCompleted: t{0}", e.WorkflowInstance.InstanceId ); };

      host.Open();
      Console.WriteLine( "Workflow host fut..." );
      Console.ReadLine();
      host.Close();
    }

Természetesen ide is kell app.config, vegyük át a MyServiceHost projektből és írjuk át néhány helyen:

  • A service tag name attribútuma ne MyServiceLib.CalcService, hanem MyWorkflowLib.CalcWorkflow legyen, hiszen ezt hosztoljuk.
  • Használjuk a 9090-es portot, hogy a korábbi szolgáltatásunk még működhessen.
  • wsHttpBinding helyett használjuk wsHttpContextBindingot, a WorkflowServices ezt szereti.
  • Ha a workflow runtime-ot is szeretnénk konfigurálni, akkor azt a <serviceBehaviors> tag alatt a <behavior> elemben tehetjük meg a WF 3.0-ban megismert XML elemekkel.

Íme a teljes system.serviceModel szekció:

    <services>
      <service name="MyWorkflowLib.CalcWorkflow" behaviorConfiguration="MyServiceLib.CalcServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress = "http://localhost:9090/CalcService/" />
              </baseAddresses>
          </host>
         <endpoint address="" binding="wsHttpContextBinding" contract="MyServiceLib.ICalcService" />
         <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyServiceLib.CalcServiceBehavior">
          <serviceMetadata httpGetEnabled="True"/>
            <!--
              <workflowRuntime name="WorkflowServiceHostRuntime" validateOnCreate="true">
                <services>
                  <add type="System.Workflow.Runtime.Hosting.SqlWorkflowPersistenceService"
                       connectionString="Data Source=.SQLExpress;Initial Catalog=WorkflowPersistenceStore;Integrated Security=True"
                       LoadIntervalSeconds="1" UnLoadOnIdle="true"  />
                </services>
              </workflowRuntime>-->
        </behavior>
      </serviceBehaviors>
    </behaviors>

Az alkalmazás ezután futtatható, de előfordulhat, hogy ezt a kivételt kapjuk:

Unhandled Exception: System.InvalidOperationException: Service ‘MyWorkflowLib.CalcWorkflow’ has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.

Ellenőrizzük ismét, hogy mindent átírtunk-e, mert bár rengeteg beállítás van a konfig fájlban, a WCF runtime nem találja, amit keres. Valószínűleg a szolgáltatás nevével lesz gond.

Workflow kliens készítése

Módosítsuk a kliens alkalmazásunkat, hogy az új szolgáltatáshoz kapcsolódjon. Szerencsére ehhez csak a konfig fájlt kell módosítani, hizsen azonos contractot használunk. A cím és a binding más:

    <system.serviceModel>
        <client>
            <endpoint
                    address="http://localhost:9090/CalcService/"
                    binding="wsHttpContextBinding"
                    contract="MyServices.ICalcService" />
        </client>
    </system.serviceModel>

Ha ez megvan, a kliensnek rá kell találnia a workflow alapú szolgáltatásunkra.

Workflow készítése SendActivity használatával

Ha már megmaradt a korábbi MyServiceHost alkalmazásunk egy másik porton, miért ne tekinthetnénk azt egy külső szolgáltatásnak és passzolhatnánk tovább a workflowba befutó kéréseket neki? A SendActivity használatával meghívhatunk külső szolgáltatásokat.

Nyissuk meg tehát a korábban elkészített workflowt és dobjunk a Toolboxról egy SendActivity-t a ReceiveActivity-be:

SendActivity egy ReceiveActivity-ben

Itt is a ServiceOperationInfo tulajdonság a kulcs, válasszuk ki a MyServiceLib.ICalcService.Add metódust, ami után a ReceiveActivity-nél látott módon van lehetőségünk a metódus paramétereinek és visszatérési értékeinek kötésére a már létrehozott helyi tulajdonságokhoz.

Hiányolja továbbá a validátor a ChannelToken tulajdonság beállítását. Ha ide tetszőleges sztringet (pl. token), írunk, lenyithatjuk a tulajdonságot és láthatjuk, hogy vár egy EndpointName értéket. Itt van tehát a kutya elhantolva, definiálnunk kell egy endpointot, ami mindent elárul a hosztnak arról, hogy hol van a meghívandó szolgáltatás. Mivel ilyet már épp csináltunk a MyClient projektnél, vegyük át az ottani app.config client szekcióját, aminek ugyan a szerkezete jó, de minden értékét módosítani kell és nevet is kell adni neki:

    <client>
        <endpoint
                name="MyServices_ICalcService"
                address="http://localhost:9091/CalcService/"
                binding="wsHttpBinding"
                contract="MyServiceLib.ICalcService" />
    </client>

A name tulajdonság értékét adjuk meg a Properties ablakban az EndpointName értékeként és máris tesztelhetjük a két hosztot és a klienst egyetlen rendszerként workflow runtime-ostul. (A CodeActivity-ben az összeadást célszerű kikommentezni.)

Összefoglalás

Készítettünk tehát egy konzolos kliens alkalmazást, ami wsHttpContextBindingon keresztül meghívja a 9090-es porton figyelő, workflow alapokon megvalósított számológép szolgáltatást. Mivel ebben nincs összeadás funkció (kikommenteztük), ezért ő továbbhív egy másik külső szolgáltatás felé, ami a 9091-es porton figyel és wsHttpBindingon keresztül érhető el. A dologban az a szép, hogy a WF gondoskodik arról, hogy az üzleti logikánk valóban sokáig futhasson és akár az újraindítást is túlélje, miközben a WCF gondoskodik a rugalmasan konfigurálható kommunikációról.

A megoldás szép, de ha valahol valami elakad vagy finomhangolni kell, akkor bizony irány a WCF+WF mélyvíz….

A cikkhez tartozó forráskód megtalálható az MSDN Kompetencia Központ honlapján, ahol a .NET 3.5 Induló Készletben Benedek Zoltán előadása részletesen érinti a workflow services témakörét is.