Sdílet prostřednictvím


Vlastní hostitel služby

Ukázka CustomServiceHost ukazuje, jak použít vlastní derivát ServiceHost třídy ke změně chování za běhu služby. Tento přístup nabízí opakovaně použitelnou alternativu ke konfiguraci velkého počtu služeb běžným způsobem. Ukázka také ukazuje, jak pomocí ServiceHostFactory třídy použít vlastní ServiceHost v hostitelském prostředí Internetová informační služba (IIS) nebo Windows Process Activation Service (WAS).

O scénáři

Aby se zabránilo neúmyslnému zpřístupnění potenciálně citlivých metadat služby, výchozí konfigurace pro služby WCF (Windows Communication Foundation) zakáže publikování metadat. Toto chování je ve výchozím nastavení zabezpečené, ale také znamená, že nemůžete použít nástroj pro import metadat (například Svcutil.exe) k vygenerování kódu klienta potřebného k volání služby, pokud není explicitně povolené chování publikování metadat služby v konfiguraci.

Povolení publikování metadat pro velký počet služeb zahrnuje přidání stejných konfiguračních prvků do každé jednotlivé služby, což vede k velkému množství konfiguračních informací, které jsou v podstatě stejné. Jako alternativu ke konfiguraci jednotlivých služeb je možné napsat imperativní kód, který umožňuje publikování metadat jednou a pak tento kód znovu použít v několika různých službách. Toho se dosahuje vytvořením nové třídy, která je odvozena z ServiceHost metody () a přepíše ApplyConfiguration() k imperativnímu přidání chování publikování metadat.

Důležité

Pro přehlednost tato ukázka ukazuje, jak vytvořit nezabezpečený koncový bod publikování metadat. Tyto koncové body jsou potenciálně dostupné anonymním neověřeným příjemcům a před nasazením těchto koncových bodů je potřeba zajistit, aby byla veřejně zpřístupněna metadata služby.

Implementace vlastního hostitele služby

Třída ServiceHost zveřejňuje několik užitečných virtuálních metod, které dědiče mohou přepsat, aby změnily chování služby za běhu. Například ApplyConfigurationmetoda () čte informace o konfiguraci služby z úložiště konfigurace a odpovídajícím způsobem mění hostitele ServiceDescription . Výchozí implementace čte konfiguraci z konfiguračního souboru aplikace. Vlastní implementace mohou přepsat ApplyConfiguration() a dále změnit ServiceDescription použití imperativního kódu nebo dokonce zcela nahradit výchozí úložiště konfigurace. Například ke čtení konfigurace koncového bodu služby z databáze místo konfiguračního souboru aplikace.

V této ukázce chceme vytvořit vlastní serviceHost, který přidá ServiceMetadataBehavior (který umožňuje publikování metadat), i když toto chování není explicitně přidáno do konfiguračního souboru služby. Chcete-li toho dosáhnout, vytvořte novou třídu, která dědí z ServiceHost a přepsání 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)
    }
}

Vzhledem k tomu, že nechceme ignorovat žádnou konfiguraci, která byla zadána v konfiguračním souboru aplikace, první věc, kterou naše přepsání ApplyConfiguration() označuje jako základní implementaci. Po dokončení této metody můžeme imperativním způsobem přidat ServiceMetadataBehavior do popisu následující imperativní kód.

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;
}

Poslední věcí, kterou musí naše ApplyConfiguration() přepsání udělat, je přidat výchozí koncový bod metadat. Podle konvence se pro každý identifikátor URI v kolekci BaseAddresses hostitele služby vytvoří jeden koncový bod metadat.

//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");
    }
}

Použití vlastního hostitele služby v místním hostiteli

Teď, když jsme dokončili vlastní implementaci ServiceHost, můžeme ji použít k přidání chování publikování metadat do jakékoli služby hostováním této služby uvnitř instance naší SelfDescribingServiceHost. Následující kód ukazuje, jak ho použít ve scénáři samoobslužného hostitele.

SelfDescribingServiceHost host =
         new SelfDescribingServiceHost( typeof( Calculator ) );
host.Open();

Náš vlastní hostitel stále čte konfiguraci koncového bodu služby z konfiguračního souboru aplikace, jako bychom k hostování služby použili výchozí ServiceHost třídu. Vzhledem k tomu, že jsme přidali logiku pro povolení publikování metadat uvnitř vlastního hostitele, už nesmíme explicitně povolit chování publikování metadat v konfiguraci. Tento přístup má jedinečnou výhodu při vytváření aplikace, která obsahuje několik služeb, a chcete povolit publikování metadat na každém z nich, aniž byste museli zapsat stejné konfigurační prvky.

Použití vlastního hostitele služby ve službě IIS nebo WAS

Použití vlastního hostitele služby ve scénářích s vlastním hostitelem je jednoduché, protože je to kód aplikace, který je nakonec zodpovědný za vytvoření a otevření instance hostitele služby. V hostitelském prostředí služby IIS nebo WAS však infrastruktura WCF dynamicky vytvoří instanci hostitele vaší služby v reakci na příchozí zprávy. V tomto hostitelském prostředí se dají použít také vlastní hostitelé služeb, ale vyžadují nějaký další kód ve formě ServiceHostFactory. Následující kód ukazuje derivát, ServiceHostFactory který vrací instance našeho vlastního 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 vidíte, implementace vlastního ServiceHostFactory je jednoduchá. Veškerá vlastní logika se nachází uvnitř implementace ServiceHost; objekt pro vytváření vrátí instanci odvozené třídy.

Abychom mohli použít vlastní továrnu s implementací služby, musíme do souboru .svc služby přidat další metadata.

<% @ServiceHost Service="Microsoft.ServiceModel.Samples.CalculatorService"
               Factory="Microsoft.ServiceModel.Samples.SelfDescribingServiceHostFactory"
               language=c# Debug="true" %>

Zde jsme do direktivy přidali další Factory atribut @ServiceHost a předali jsme název typu CLR naší vlastní továrny jako hodnotu atributu. Když služba IIS nebo WAS obdrží zprávu pro tuto službu, infrastruktura hostování WCF nejprve vytvoří instanci ServiceHostFactory a potom vytvoří instanci hostitele služby samotné voláním ServiceHostFactory.CreateServiceHost().

Spuštění ukázky

I když tato ukázka poskytuje plně funkční implementaci klienta a služby, je cílem ukázky ilustrovat, jak změnit chování služby za běhu pomocí vlastního hostitele., proveďte následující kroky:

Sledujte účinek vlastního hostitele.

  1. Otevřete soubor Web.config služby a všimněte si, že pro službu není explicitně povolována žádná konfigurace.

  2. Otevřete soubor .svc služby a všimněte si, že jeho @ServiceHost direktiva obsahuje atribut Factory, který určuje název vlastní serviceHostFactory.

Nastavení, sestavení a spuštění ukázky

  1. Ujistěte se, že jste pro ukázky windows Communication Foundation provedli jednorázovou instalační proceduru.

  2. Pokud chcete sestavit řešení, postupujte podle pokynů v části Sestavení ukázek Windows Communication Foundation.

  3. Po sestavení řešení spusťte Setup.bat a nastavte aplikaci ServiceModelSamples ve službě IIS 7.0. Adresář ServiceModelSamples by se teď měl zobrazit jako aplikace IIS 7.0.

  4. Pokud chcete spustit ukázku v konfiguraci s jedním nebo více počítači, postupujte podle pokynů v části Spuštění ukázek windows Communication Foundation.

  5. Aplikaci IIS 7.0 odeberete spuštěním Cleanup.bat.

Viz také