Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
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. Przykład pokazuje również, jak używać klasy ServiceHostFactory do zastosowania niestandardowego hosta ServiceHost w środowisku usług Internet Information Services (IIS) lub Windows Process Activation Service (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 klasy ServiceHost i nadpisuje metodę ApplyConfiguration
(), aby imperatywnie dodać funkcję publikacji 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 hosta ServiceHost
Klasa ServiceHost udostępnia kilka przydatnych metod wirtualnych, które dziedziczący mogą przesłonić, aby zmienić zachowanie usługi w czasie wykonywania. Na przykład metoda ApplyConfiguration
() odczytuje informacje o konfiguracji usługi z magazynu konfiguracji i odpowiednio zmienia konfigurację hosta ServiceDescription. Domyślna implementacja odczytuje konfigurację z pliku konfiguracji aplikacji. Implementacje niestandardowe mogą przesłonić ApplyConfiguration
(), aby jeszcze bardziej zmienić element ServiceDescription w celu użycia 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ć nasze ApplyConfiguration
() nadpisanie, jest dodanie domyślnego punktu końcowego metadanych. Zgodnie z konwencją dla każdego URI w kolekcji adresów bazowych hosta usługi tworzony jest jeden punkt dostępu metadanych.
//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 w samodzielnym hostowaniu
Teraz, gdy ukończyliśmy naszą niestandardową implementację ServiceHost, możemy jej użyć do dodania zachowania publikowania metadanych do dowolnej usługi poprzez hostowanie tej usługi wewnątrz naszej instancji SelfDescribingServiceHost
. 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 hostowania jest proste, ponieważ to kod aplikacji jest ostatecznie odpowiedzialny za tworzenie i otwieranie instancji hosta usługi. Jednak w środowisku hostingu IIS lub WAS infrastruktura WCF dynamicznie tworzy wystąpienie hosta usługi w odpowiedzi na przychodzące komunikaty. 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 instancje naszego niestandardowego SelfDescribingServiceHost
.
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ę w implementacji ServiceHost; fabryka zwraca instancję 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 zdefiniowanej przez użytkownika jako wartość tego atrybutu. Gdy IIS lub WAS otrzymują komunikat dla tej usługi, infrastruktura hostingu WCF najpierw tworzy instancję ServiceHostFactory, a następnie inicjuje hosta usługi, wywołując ServiceHostFactory.CreateServiceHost()
.
Uruchamianie przykładu
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:
Obserwuj wpływ hosta niestandardowego
Otwórz plik Web.config usługi i upewnij się, że nie ma konfiguracji jawnie włączającej metadane 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 One-Time 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 Uruchamianie przykładów programu Windows Communication Foundation.
Aby usunąć aplikację IIS 7.0, uruchom Cleanup.bat.