Pri programovaní vo WCF máme vždy na výber viacero možností. Platí to aj o hostingu WCF služieb. Pozrime sa aké sú možnosti a ako ich implementovať.
reklama
Pri programovaní vo WCF máme vždy na výber viacero možností. Platí to aj o hostingu WCF služieb. Pozrime sa aké sú možnosti a ako ich implementovať.
WCF službu môžeme hostovať v hociakom prostredí, ktoré podporuje spravovaný kód (managed code). Samotný pojem hosting vo WCF znamená prostredie, ktoré vytvára službu a kontroluje jej životný cyklus. Máme 2 základné možnosti hostovania WCF služieb:
- self-hosting,
- hosting v IIS.
Self-hosting
Pri použití self-hostingu vývojár musí napísať vlastný hostovací kód. Ak sa rozhodneme pre self-hosting, tak si môžeme vybrať z nasledovných možností:
- self-hosting v konzolovej aplikácii - životný cyklus služby môžeme kontrolovať z metódy
Main.
- self-hosting vo WinForms aplikácii - životný cyklus služby môžeme kontrolovať v prekrytých (override) metódach
OnLoad a OnClosing triedy System.Windows.Forms.Form.
- self-hosting v službe systému Windows - životný cyklus služby kontrolujeme v prekrytých metódach
OnStart a OnStop triedy System.ServiceProcess.ServiceBase.
Základ implementácie self-hostingu spočíva v použití triedy System.ServiceModel.ServiceHost s ktorou sme sa už naučili pracovať v predchádzajúcich častiach seriálu:
ServiceHost host = new ServiceHost(typeof(SomeService));
host.Open();
// ....
host.Close();
Hosting WCF služby v IIS
Pri IIS hostingu vývojár vytvorí virtuálny adresár a definuje službu pomocou .svc súboru. IIS hosting môžeme rozdeliť do 2 skupín:
- hosting v IIS 5.1 a IIS 6 - môžeme hostovať iba služby, ktoré majú endpointy s binding-ami komunikujúcimi cez HTTP.
- hosting v IIS 7 - tu môžeme hostovať služby používajúce hociaký transportný protokol. V IIS 7, ktoré je súčasťou Windows Vista slúži na hostovanie WCF služieb prostredie Windows Activation Service (WAS).
IIS hosting má v porovnaní so self-hostingom nasledovné výhody:
- škálovateľnosť,
- spoľahlivosť (health management, process isolation, application domain isolation),
- tolerancia voči chybám (ak sa počas behu služby vyskytne neošetrená výnimka, IIS zabezpečí automatický reštart služby).
Príklad
V praktickom príklade si ukážeme dve zo spomínaných možností a to hostovanie WCF služby v IIS a v službe systému Windows (Windows service). Solution bude celkovo pozostávať z 5 projektov.
Service
Aby sme mali čo hostovať, vytvoríme jednoduchú službu s jednou operáciou, ktorá vracia aktuálny čas ako reťazec. Toto bude prvý projekt v solution a bude typu WCF Service Library. C# kód kontraktu služby a implementačnej triedy služby bude:
using System;
using System.ServiceModel;
namespace TimeService
{
[ServiceContract]
public interface ITimeProvider
{
[OperationContract]
string GetCurrentTime();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class TimeProvider : ITimeProvider
{
#region ITimeProvider Members
public string GetCurrentTime()
{
return DateTime.Now.ToLongTimeString();
}
#endregion
}
}
IIS Host
Pre hostovanie WCF služby v IIS pridáme do solution nový website voľbou Add - New Web Site:

Potom v zobrazenom okne zvolíme WCF Service:

Vo vytvorenom projekte nás bude zaujímať predovšetkým súbor s príponou .svc (Service.svc). Pokiaľ máme skúsenosti s ASP.NET, tak na .svc súbor sa môžeme pozerať ako na .aspx súbor. C# kód služby môžeme priamo napísať do .svc súboru alebo môžeme priradiť k .svc súboru codebehind C# súbor a tam napísať kód služby.
Teda stačí z projektu služby do .svc súboru skopírovať C# kód pomocou CTRL+C a CTRL+V. To som však nemyslel vážne ;) .... je to predsa neprofesionálne riešenie. Takto by sme vytvorili duplicitu a duplicity znamenajú veľké zlo v softvérovom priemysle. Keďže chceme kód služby zdielať medzi viacerými projektami v rámci solution,
je umiestnený do samostatnej assembly (.dll knižnice). Potom stačí do tohto projektu pridať referenciu na projekt služby. Výsledný kód .svc súboru bude obsahovať iba direktívy <%@ ServiceHost %> a <%@ Assembly %>:
<%@ ServiceHost Language=C# Debug="true" Service="TimeService.TimeProvider" %>
<%@ Assembly Name="TimeService" %>
Konfigurácia služby tentoraz nebude v súbore App.config ale v súbore Web.config:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="TimeService.TimeProvider"
behaviorConfiguration="metadata">
<endpoint contract="TimeService.ITimeProvider"
binding="wsHttpBinding" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="metadata">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.web>
<compilation debug="true" />
</system.web>
</configuration>
Ak by sme do prehliadača skúsili zadať adresu .svc súboru, uvideli by sme stránku s popisom služby a s odkazom na WSDL definíciu služby:

Klient (IIS Host)
Tretím projektom v solution bude klient (konzolová aplikácia) služby hostovanej v IIS. Klient bude komunikovať so službou pomocou proxy triedy, ktorú vygenerujeme voľbou Add Service Reference, pričom zadáme URI k súboru Service.svc:

C# kód klienta využívajúci proxy triedu TimeProviderClient:
using System;
using IisClient.TimeProvider;
namespace IisClient
{
class Program
{
static void Main(string[] args)
{
using (TimeProviderClient client = new TimeProviderClient())
{
Console.Write(client.GetCurrentTime());
Console.ReadLine();
}
}
}
}
Ku klientovi doplníme konfiguračný súbor v ktorom nastavíme jeden endpoint:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint address="http://localhost/wcf/wcfservice/Service.svc"
binding="wsHttpBinding"
contract="IisClient.TimeProvider.ITimeProvider" />
</client>
</system.serviceModel>
</configuration>
Windows Service Host
Štvrtým projektom v solution bude služba systému Windows, ktorá bude slúžiť ako hostovacie prostredie pre WCF službu. Do solution pridáme projekt typu Windows Service:

Základným krokom pri vytvorení systémovej služby je vytvorenie triedy odvodenej od triedy System.ServiceProcess.ServiceBase a prekrytie vybraných metód v ktorých implementujeme vlastnú funkcionalitu. C# kód systémovej služby bude:
using System;
using System.ServiceModel;
using System.ServiceProcess;
namespace WindowsServiceHost
{
public partial class WcfHostingService : ServiceBase
{
private ServiceHost host;
public WcfHostingService()
{
ServiceName = "WcfHostingService";
InitializeComponent();
}
protected override void OnStart(string[] args)
{
if (host != null) host.Close();
host = new ServiceHost(typeof(TimeService.TimeProvider));
host.Open();
}
protected override void OnStop()
{
host.Close();
host = null;
}
}
}
V tomto kóde sú zaujímavé menné priestory (namespaces) System.ServiceModel a System.ServiceProcess. Na prvý pohľad by sa mohlo zdať, že tieto menné priestory spolu nejako súvisia, no nie je to tak. System.ServiceModel je základný menný priestor WCF, System.ServiceProcess je menný priestor zoskupujúci triedy týkajúce sa služieb systému Windows.
K systémovej službe je potrebné vytvoriť ešte triedu inštalátora. V tomto inštalátore nastavíme účet pod ktorým bude služba spustená, meno služby, zobrazované meno služby a spôsob spustenia služby:
using System;
using System.ServiceProcess;
using System.ComponentModel;
using System.Configuration.Install;
namespace WindowsServiceHost
{
[RunInstaller(true)]
public class WindowsServiceInstaller : Installer
{
public WindowsServiceInstaller()
{
ServiceProcessInstaller spi = new ServiceProcessInstaller();
spi.Account = ServiceAccount.LocalSystem;
ServiceInstaller si = new ServiceInstaller();
si.DisplayName = "WCF Service Host";
si.ServiceName = "WcfHostingService";
si.StartType = ServiceStartMode.Automatic;
Installers.Add(spi);
Installers.Add(si);
}
}
}
Konfiguračný súbor bude:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="TimeService.TimeProvider"
behaviorConfiguration="metadata">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8008/" />
</baseAddresses>
</host>
<endpoint address="TimeProvider"
binding="wsHttpBinding"
contract="TimeService.ITimeProvider" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="metadata">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Klient (Windows Service Host)
Piatym projektom v solution bude klient (konzolová aplikácia) služby hostovanej v službe systému Windows (systémová služba). Vytvoríme ho podobne ako klienta služby hostovanej v IIS:
using System;
using WindowsServiceClient.TimeProvider;
namespace WindowsServiceClient
{
class Program
{
static void Main(string[] args)
{
using (TimeProviderClient client = new TimeProviderClient())
{
Console.Write(client.GetCurrentTime());
Console.ReadLine();
}
}
}
}
V konfiguračnom súbore klienta nastavíme potrebný endpoint:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint address="http://localhost:8008/TimeProvider"
binding="wsHttpBinding"
contract="WindowsServiceClient.TimeProvider.ITimeProvider" />
</client>
</system.serviceModel>
</configuration>
Nakoniec môžeme prakticky otestovať obe riešenia hostovania. Pred použitím hostovania v systémovej službe, musíme najprv túto službu nainštalovať do systému. Na to nám poslúži utilita installutil, ktorú odporúčam spustiť z prostredia SDK Command Prompt (nájdeme ho v ponuke Štart v Microsoft .NET Framework SDK v2.0).
Systémovú službu nainštalujeme príkazom:
installutil WindowsServiceHost.exe
Odinštalujeme ju pomocou:
installutil /u WindowsServiceHost.exe
Po nainštalovaní systémovú službu môžeme spustiť pomocou MMC alebo príkazom:
net start WcfHostingService
Zastavíme ju príkazom:
net stop WcfHostingService
Všetky zdrojové kódy si môžete stiahnúť tu.
Ing. Marián Košťál (csharp@azet.sk)