Anpassad tjänstvärd
CustomServiceHost-exemplet visar hur du använder ett anpassat derivat av ServiceHost klassen för att ändra körningsbeteendet för en tjänst. Den här metoden är ett återanvändbart alternativ till att konfigurera ett stort antal tjänster på ett vanligt sätt. Exemplet visar också hur du använder ServiceHostFactory klassen för att använda en anpassad ServiceHost i värdmiljön Internet Information Services (IIS) eller Windows Process Activation Service (WAS).
Om scenariot
För att förhindra oavsiktligt avslöjande av potentiellt känsliga tjänstmetadata inaktiverar standardkonfigurationen för WCF-tjänster (Windows Communication Foundation) metadatapublicering. Det här beteendet är säkert som standard, men innebär också att du inte kan använda ett verktyg för metadataimport (till exempel Svcutil.exe) för att generera den klientkod som krävs för att anropa tjänsten om inte tjänstens beteende för metadatapublicering uttryckligen är aktiverat i konfigurationen.
Att aktivera metadatapublicering för ett stort antal tjänster innebär att samma konfigurationselement läggs till i varje enskild tjänst, vilket resulterar i en stor mängd konfigurationsinformation som i stort sett är densamma. Som ett alternativ till att konfigurera varje tjänst individuellt är det möjligt att skriva den imperativa kod som möjliggör metadatapublicering en gång och sedan återanvända koden i flera olika tjänster. Detta uppnås genom att skapa en ny klass som härleds från ServiceHost och åsidosätter ApplyConfiguration
metoden () för att imperativt lägga till beteendet för metadatapublicering.
Viktigt!
För tydlighetens skull visar det här exemplet hur du skapar en oskyddad slutpunkt för metadatapublicering. Sådana slutpunkter är potentiellt tillgängliga för anonyma oautentiserade konsumenter och försiktighet måste vidtas innan sådana slutpunkter distribueras för att säkerställa att offentligt avslöjande av en tjänsts metadata är lämpligt.
Implementera en anpassad ServiceHost
Klassen ServiceHost exponerar flera användbara virtuella metoder som ärver kan åsidosätta för att ändra körningsbeteendet för en tjänst. Metoden () läser till exempel ApplyConfiguration
tjänstkonfigurationsinformation från konfigurationsarkivet och ändrar värdens ServiceDescription i enlighet med detta. Standardimplementeringen läser konfigurationen från programmets konfigurationsfil. Anpassade implementeringar kan åsidosätta ApplyConfiguration
() för att ytterligare ändra ServiceDescription den imperativa koden eller ersätta standardkonfigurationsarkivet helt. Om du till exempel vill läsa en tjänsts slutpunktskonfiguration från en databas i stället för programmets konfigurationsfil.
I det här exemplet vill vi skapa en anpassad ServiceHost som lägger till ServiceMetadataBehavior (som möjliggör metadatapublicering) även om det här beteendet inte uttryckligen läggs till i tjänstens konfigurationsfil. För att åstadkomma detta skapar du en ny klass som ärver från ServiceHost och åsidosätter 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)
}
}
Eftersom vi inte vill ignorera någon konfiguration som har angetts i programmets konfigurationsfil, är det första som åsidosättningen av ApplyConfiguration
() gör att anropa basimplementeringen. När den här metoden är klar kan vi absolut lägga till i ServiceMetadataBehavior beskrivningen med hjälp av följande imperativa kod.
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;
}
Det sista vår () åsidosättning ApplyConfiguration
måste göra är att lägga till standardslutpunkten för metadata. Enligt konventionen skapas en metadataslutpunkt för varje URI i tjänstvärdens BaseAddresses-samling.
//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");
}
}
Använda en anpassad ServiceHost i en egen värd
Nu när vi har slutfört vår anpassade ServiceHost-implementering kan vi använda den för att lägga till beteende för metadatapublicering i alla tjänster genom att vara värd för den tjänsten i en instans av vår SelfDescribingServiceHost
. Följande kod visar hur du använder den i scenariot med självvärdar.
SelfDescribingServiceHost host =
new SelfDescribingServiceHost( typeof( Calculator ) );
host.Open();
Vår anpassade värd läser fortfarande tjänstens slutpunktskonfiguration från programmets konfigurationsfil, som om vi hade använt standardklassen ServiceHost som värd för tjänsten. Men eftersom vi har lagt till logiken för att aktivera metadatapublicering i vår anpassade värd, måste vi inte längre uttryckligen aktivera beteendet för metadatapublicering i konfigurationen. Den här metoden har en tydlig fördel när du skapar ett program som innehåller flera tjänster och du vill aktivera metadatapublicering på var och en av dem utan att skriva samma konfigurationselement om och om.
Använda en anpassad ServiceHost i IIS eller WAS
Det är enkelt att använda en anpassad tjänstvärd i scenarier med egen värd eftersom det är din programkod som är ytterst ansvarig för att skapa och öppna tjänstvärdinstansen. I IIS- eller WAS-värdmiljön instansierar dock WCF-infrastrukturen dynamiskt tjänstens värd som svar på inkommande meddelanden. Anpassade tjänstvärdar kan också användas i den här värdmiljön, men de kräver ytterligare kod i form av en ServiceHostFactory. Följande kod visar ett derivat av ServiceHostFactory som returnerar instanser av vår anpassade 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);
}
}
Som du ser är det enkelt att implementera en anpassad ServiceHostFactory. All anpassad logik finns i ServiceHost-implementeringen. fabriken returnerar en instans av den härledda klassen.
Om du vill använda en anpassad fabrik med en tjänstimplementering måste vi lägga till ytterligare metadata i tjänstens .svc-fil.
<% @ServiceHost Service="Microsoft.ServiceModel.Samples.CalculatorService"
Factory="Microsoft.ServiceModel.Samples.SelfDescribingServiceHostFactory"
language=c# Debug="true" %>
Här har vi lagt till ytterligare ett Factory
attribut i @ServiceHost
direktivet och skickat CLR-typnamnet för vår anpassade fabrik som attributets värde. När IIS eller WAS tar emot ett meddelande för den här tjänsten skapar WCF-värdinfrastrukturen först en instans av ServiceHostFactory och instansierar sedan själva tjänstvärden genom att anropa ServiceHostFactory.CreateServiceHost()
.
Köra exemplet
Även om det här exemplet ger en fullt fungerande klient- och tjänstimplementering är poängen med exemplet att illustrera hur du ändrar en tjänsts körningsbeteende med hjälp av en anpassad värd. Gör följande:
Observera effekten av den anpassade värden
Öppna tjänstens Web.config-fil och observera att det inte finns någon konfiguration som uttryckligen aktiverar metadata för tjänsten.
Öppna tjänstens .svc-fil och observera att dess @ServiceHost direktiv innehåller ett Factory-attribut som anger namnet på en anpassad ServiceHostFactory.
Konfigurera, skapa och köra exemplet
Kontrollera att du har utfört engångsinstallationsproceduren för Windows Communication Foundation-exempel.
Skapa lösningen genom att följa anvisningarna i Skapa Windows Communication Foundation-exempel.
När lösningen har skapats kör du Setup.bat för att konfigurera ServiceModelSamples-programmet i IIS 7.0. Katalogen ServiceModelSamples bör nu visas som ett IIS 7.0-program.
Om du vill köra exemplet i en konfiguration med en eller flera datorer följer du anvisningarna i Köra Windows Communication Foundation-exempel.
Om du vill ta bort IIS 7.0-programmet kör du Cleanup.bat.