Niestandardowy host usługi
W przykładzie CustomServiceHost pokazano, jak za pomocą niestandardowej pochodnej ServiceHost klasy zmienić zachowanie usługi w czasie wykonywania. Takie podejście zapewnia alternatywę wielokrotnego użytku w celu skonfigurowania dużej liczby usług w typowy sposób. W przykładzie pokazano również, jak używać ServiceHostFactory klasy do używania niestandardowego hosta ServiceHost w usługach Internet Information Services (IIS) lub w środowisku hostingu usługi aktywacji procesów systemu Windows (WAS).
Informacje o scenariuszu
Aby zapobiec przypadkowemu ujawnieniu potencjalnie poufnych metadanych usługi, domyślna konfiguracja usług Windows Communication Foundation (WCF) wyłącza publikowanie metadanych. To zachowanie jest domyślnie bezpieczne, ale oznacza również, że nie można użyć narzędzia importowania metadanych (takiego jak Svcutil.exe), aby wygenerować kod klienta wymagany do wywołania usługi, chyba że zachowanie publikowania metadanych usługi jest jawnie włączone w konfiguracji.
Włączenie publikowania metadanych dla dużej liczby usług obejmuje dodanie tych samych elementów konfiguracji do każdej pojedynczej usługi, co skutkuje dużą ilością informacji o konfiguracji, które są zasadniczo takie same. Alternatywą dla poszczególnych usług jest napisanie kodu imperatywnego, który umożliwia publikowanie metadanych raz, a następnie ponowne użycie tego kodu w kilku różnych usługach. Jest to realizowane przez utworzenie nowej klasy, która pochodzi z ServiceHost metody () i zastępuje ApplyConfiguration
metodę (), aby w sposób imperatywny dodać zachowanie publikowania metadanych.
Ważne
W celu zapewnienia przejrzystości w tym przykładzie pokazano, jak utworzyć niezabezpieczony punkt końcowy publikowania metadanych. Takie punkty końcowe są potencjalnie dostępne dla anonimowych nieuwierzytelnionych użytkowników i należy zachować ostrożność przed wdrożeniem takich punktów końcowych, aby zapewnić, że publiczne ujawnienie metadanych usługi jest odpowiednie.
Implementowanie niestandardowego elementu ServiceHost
Klasa ServiceHost uwidacznia kilka przydatnych metod wirtualnych, które dziedziczą, mogą przesłonić zachowanie usługi w czasie wykonywania. Na przykład ApplyConfiguration
metoda () odczytuje informacje o konfiguracji usługi z magazynu konfiguracji i odpowiednio zmienia host ServiceDescription . Domyślna implementacja odczytuje konfigurację z pliku konfiguracji aplikacji. Implementacje niestandardowe mogą przesłonić ApplyConfiguration
(), aby jeszcze bardziej zmienić ServiceDescription użycie kodu imperatywnego, a nawet całkowicie zastąpić domyślny magazyn konfiguracji. Na przykład aby odczytać konfigurację punktu końcowego usługi z bazy danych zamiast pliku konfiguracji aplikacji.
W tym przykładzie chcemy utworzyć niestandardowy element ServiceHost, który dodaje element ServiceMetadataBehavior (który umożliwia publikowanie metadanych), nawet jeśli to zachowanie nie zostało jawnie dodane w pliku konfiguracji usługi. Aby to osiągnąć, utwórz nową klasę, która dziedziczy z ServiceHost i zastępuje ApplyConfiguration
().
class SelfDescribingServiceHost : ServiceHost
{
public SelfDescribingServiceHost(Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses) { }
//Overriding ApplyConfiguration() allows us to
//alter the ServiceDescription prior to opening
//the service host.
protected override void ApplyConfiguration()
{
//First, we call base.ApplyConfiguration()
//to read any configuration that was provided for
//the service we're hosting. After this call,
//this.Description describes the service
//as it was configured.
base.ApplyConfiguration();
//(rest of implementation elided for clarity)
}
}
Ponieważ nie chcemy ignorować żadnej konfiguracji podanej w pliku konfiguracji aplikacji, pierwszą rzeczą, którą zastępujemy ApplyConfiguration
(), jest wywołanie implementacji podstawowej. Po zakończeniu tej metody możemy w sposób imperatywny dodać element ServiceMetadataBehavior do opisu przy użyciu następującego kodu imperatywnego.
ServiceMetadataBehavior mexBehavior = this.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (mexBehavior == null)
{
mexBehavior = new ServiceMetadataBehavior();
this.Description.Behaviors.Add(mexBehavior);
}
else
{
//Metadata behavior has already been configured,
//so we do not have any work to do.
return;
}
Ostatnią rzeczą, jaką musi wykonać nasz ApplyConfiguration
() przesłonięcia, jest dodanie domyślnego punktu końcowego metadanych. Zgodnie z konwencją jeden punkt końcowy metadanych jest tworzony dla każdego identyfikatora URI w kolekcji BaseAddresses hosta usługi.
//Add a metadata endpoint at each base address
//using the "/mex" addressing convention
foreach (Uri baseAddress in this.BaseAddresses)
{
if (baseAddress.Scheme == Uri.UriSchemeHttp)
{
mexBehavior.HttpGetEnabled = true;
this.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpBinding(),
"mex");
}
else if (baseAddress.Scheme == Uri.UriSchemeHttps)
{
mexBehavior.HttpsGetEnabled = true;
this.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpsBinding(),
"mex");
}
else if (baseAddress.Scheme == Uri.UriSchemeNetPipe)
{
this.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexNamedPipeBinding(),
"mex");
}
else if (baseAddress.Scheme == Uri.UriSchemeNetTcp)
{
this.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexTcpBinding(),
"mex");
}
}
Używanie niestandardowego hosta ServiceHost we własnym hoście
Teraz, gdy ukończyliśmy naszą niestandardową implementację ServiceHost, możemy jej użyć do dodania zachowania publikowania metadanych do dowolnej usługi przez hostowanie tej usługi w wystąpieniu naszego SelfDescribingServiceHost
obiektu . Poniższy kod pokazuje, jak używać go w scenariuszu samodzielnego hosta.
SelfDescribingServiceHost host =
new SelfDescribingServiceHost( typeof( Calculator ) );
host.Open();
Nasz host niestandardowy nadal odczytuje konfigurację punktu końcowego usługi z pliku konfiguracji aplikacji, tak jakbyśmy używali domyślnej ServiceHost klasy do hostowania usługi. Jednak ponieważ dodaliśmy logikę umożliwiającą publikowanie metadanych wewnątrz naszego niestandardowego hosta, nie musimy już jawnie włączać zachowania publikowania metadanych w konfiguracji. Takie podejście ma wyraźną przewagę podczas kompilowania aplikacji zawierającej kilka usług i chcesz włączyć publikowanie metadanych na każdym z nich bez konieczności pisania tych samych elementów konfiguracji.
Używanie niestandardowego hosta serviceHost w usługach IIS lub WAS
Używanie niestandardowego hosta usługi w scenariuszach samodzielnego hosta jest proste, ponieważ jest to kod aplikacji, który jest ostatecznie odpowiedzialny za tworzenie i otwieranie wystąpienia hosta usługi. Jednak w środowisku hostingu USŁUG IIS lub WAS infrastruktura WCF dynamicznie tworzy wystąpienie hosta usługi w odpowiedzi na komunikaty przychodzące. Hosty usług niestandardowych mogą być również używane w tym środowisku hostingu, ale wymagają one dodatkowego kodu w postaci serviceHostFactory. Poniższy kod przedstawia pochodną ServiceHostFactory , która zwraca wystąpienia niestandardowego SelfDescribingServiceHost
elementu .
public class SelfDescribingServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType,
Uri[] baseAddresses)
{
//All the custom factory does is return a new instance
//of our custom host class. The bulk of the custom logic should
//live in the custom host (as opposed to the factory)
//for maximum
//reuse value outside of the IIS/WAS hosting environment.
return new SelfDescribingServiceHost(serviceType,
baseAddresses);
}
}
Jak widać, implementacja niestandardowego elementu ServiceHostFactory jest prosta. Cała logika niestandardowa znajduje się wewnątrz implementacji ServiceHost; fabryka zwraca wystąpienie klasy pochodnej.
Aby używać fabryki niestandardowej z implementacją usługi, musimy dodać dodatkowe metadane do pliku .svc usługi.
<% @ServiceHost Service="Microsoft.ServiceModel.Samples.CalculatorService"
Factory="Microsoft.ServiceModel.Samples.SelfDescribingServiceHostFactory"
language=c# Debug="true" %>
W tym miejscu dodaliśmy dodatkowy Factory
atrybut do @ServiceHost
dyrektywy i przekazaliśmy nazwę typu CLR naszej fabryki niestandardowej jako wartość atrybutu. Gdy usługi IIS lub WAS odbierają komunikat dla tej usługi, infrastruktura hostingu WCF najpierw tworzy wystąpienie klasy ServiceHostFactory, a następnie tworzy wystąpienie hosta usługi przez wywołanie metody ServiceHostFactory.CreateServiceHost()
.
Uruchamianie przykładowej aplikacji
Mimo że ten przykład zapewnia w pełni funkcjonalną implementację klienta i usługi, punktem przykładu jest zilustrowanie sposobu zmiany zachowania czasu wykonywania usługi za pomocą niestandardowego hosta. Wykonaj następujące czynności:
Obserwowanie wpływu hosta niestandardowego
Otwórz plik Web.config usługi i sprawdź, czy nie ma jawnego włączania metadanych dla usługi.
Otwórz plik svc usługi i zwróć uwagę, że jej @ServiceHost dyrektywa zawiera atrybut Factory, który określa nazwę niestandardowego elementu ServiceHostFactory.
Konfigurowanie, kompilowanie i uruchamianie przykładu
Upewnij się, że wykonano procedurę instalacji jednorazowej dla przykładów programu Windows Communication Foundation.
Aby skompilować rozwiązanie, postępuj zgodnie z instrukcjami w temacie Building the Windows Communication Foundation Samples (Tworzenie przykładów programu Windows Communication Foundation).
Po utworzeniu rozwiązania uruchom Setup.bat, aby skonfigurować aplikację ServiceModelSamples w usługach IIS 7.0. Katalog ServiceModelSamples powinien teraz być wyświetlany jako aplikacja usług IIS 7.0.
Aby uruchomić przykład w konfiguracji pojedynczej lub między maszynami, postępuj zgodnie z instrukcjami w temacie Uruchamianie przykładów programu Windows Communication Foundation.
Aby usunąć aplikację usług IIS 7.0, uruchom Cleanup.bat.