Host di servizi personalizzatiCustom Service Host

Questo esempio dimostra come usare un derivato personalizzato della classe ServiceHost per modificare il comportamento in fase di esecuzione di un servizio.This sample demonstrates how to use a custom derivative of the ServiceHost class to alter the run-time behavior of a service. Questo approccio fornisce un'alternativa riusabile alla configurazione tradizionale di un gran numero di servizi.This approach provides a reusable alternative to configuring a large number of services in a common way. In questo esempio viene inoltre illustrato come impiegare la classe ServiceHostFactory per usare un ServiceHost personalizzato nell'ambiente di hosting Internet Information Services (IIS) o nel servizio di attivazione dei processi di Windows (WAS, Windows Process Activation Service).The sample also demonstrates how to use the ServiceHostFactory class to use a custom ServiceHost in the Internet Information Services (IIS) or Windows Process Activation Service (WAS) hosting environment.

Importante

È possibile che gli esempi siano già installati nel computer.The samples may already be installed on your machine. Verificare la directory seguente (impostazione predefinita) prima di continuare.Check for the following (default) directory before continuing.

<InstallDrive>:\WF_WCF_Samples

Se questa directory non esiste, andare al Windows Communication Foundation (WCF) e gli esempi di Windows Workflow Foundation (WF) per .NET Framework 4 per scaricare tutti i Windows Communication Foundation (WCF) e WFWF esempi.If this directory does not exist, go to Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 to download all Windows Communication Foundation (WCF) and WFWF samples. Questo esempio si trova nella directory seguente.This sample is located in the following directory.

<InstallDrive>:\WF_WCF_Samples\WCF\Extensibility\Hosting\CustomServiceHost

Informazioni sullo scenarioAbout the Scenario

Per evitare la diffusione accidentale di metadati del servizio potenzialmente riservati, la configurazione predefinita per i servizi Windows Communication Foundation (WCF) disabilita la pubblicazione dei metadati.To prevent unintentional disclosure of potentially sensitive service metadata, the default configuration for Windows Communication Foundation (WCF) services disables metadata publishing. Questo comportamento è protetto per impostazione predefinita, ma significa inoltre che non è possibile usare uno strumento di importazione di metadati (ad esempio Svcutil.exe) per generare il codice client necessario per chiamare il servizio, a meno che il comportamento del servizio di pubblicazione dei metadati non venga abilitato in modo esplicito in fase di configurazione.This behavior is secure by default, but also means that you cannot use a metadata import tool (such as Svcutil.exe) to generate the client code required to call the service unless the service’s metadata publishing behavior is explicitly enabled in configuration.

L'abilitazione della pubblicazione dei metadati per un gran numero di servizi comporta l'aggiunta degli stessi elementi di configurazione a ciascun singolo servizio, che produce una quantità elevata di informazioni di configurazione sostanzialmente uguali.Enabling metadata publishing for a large number of services involves adding the same configuration elements to each individual service, which results in a large amount of configuration information that is essentially the same. Come alternativa alla configurazione di ogni singolo servizio, è possibile scrivere il codice imperativo che consente la pubblicazione dei metadati una volta e riusare quindi tale codice su vari servizi diversi.As an alternative to configuring each service individually, it is possible to write the imperative code that enables metadata publishing once and then reuse that code across several different services. Ciò viene ottenuto creando una nuova classe che viene derivata da ServiceHost ed esegue l'override del metodo ApplyConfiguration() per aggiungere imperativamente il comportamento di pubblicazione di metadati.This is accomplished by creating a new class that derives from ServiceHost and overrides the ApplyConfiguration() method to imperatively add the metadata publishing behavior.

Importante

Per maggior chiarezza, questo esempio illustra come creare un endpoint non protetto per la configurazione di metadati.For clarity, this sample demonstrates how to create an unsecured metadata publishing endpoint. Tali endpoint sono potenzialmente disponibili per utenti anonimi non autenticati e bisogna fare attenzione prima di distribuirli per garantire che la pubblicazione dei metadati di un servizio sia appropriata.Such endpoints are potentially available to anonymous unauthenticated consumers and care must be taken before deploying such endpoints to ensure that publicly disclosing a service’s metadata is appropriate.

Implementazione di un ServiceHost personalizzatoImplementing a Custom ServiceHost

La classe ServiceHost espone diversi metodi virtuali utili che possono essere sottoposti a override dagli eredi per modificare il comportamento di un servizio in fase di esecuzione.The ServiceHost class exposes several useful virtual methods that inheritors can override to alter the run-time behavior of a service. Ad esempio, il metodo ApplyConfiguration() legge informazioni di configurazione del servizio dall'archivio di configurazione e modifica di conseguenza ServiceDescription dell'host.For example, the ApplyConfiguration() method reads service configuration information from the configuration store and alters the host's ServiceDescription accordingly. L'implementazione predefinita legge la configurazione dal file di configurazione dell'applicazione.The default implementation reads configuration from the application’s configuration file. Le implementazioni personalizzate possono eseguire l'override di ApplyConfiguration() per alterare ulteriormente la ServiceDescription usando codice imperativo o anche sostituire completamente l'archivio di configurazione predefinito.Custom implementations can override ApplyConfiguration() to further alter the ServiceDescription using imperative code or even replace the default configuration store entirely. Ad esempio, per leggere la configurazione dell'endpoint di un servizio da un database anziché il file di configurazione dell'applicazione.For example, to read a service’s endpoint configuration from a database instead of the application’s configuration file.

In questo esempio si desidera compilare un ServiceHost personalizzato che aggiunge il ServiceMetadataBehavior, (il quale consente la pubblicazione di metadati) anche se questo comportamento non viene aggiunto in modo esplicito nel file di configurazione del servizio.In this sample, we want to build a custom ServiceHost that adds the ServiceMetadataBehavior, (which enables metadata publishing), even if this behavior is not explicitly added in the service’s configuration file. Per ottenere questo risultato, viene creata una nuova classe che eredita da ServiceHost ed esegue l'override di ApplyConfiguration().To accomplish this, we create a new class that inherits from ServiceHost and overrides 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)  
    }  
}  

Poiché ogni configurazione fornita nel file di configurazione dell'applicazione non va ignorata, la prima operazione di override di ApplyConfiguration() è chiamare l'implementazione di base.Because we do not want to ignore any configuration that has been provided in the application’s configuration file, the first thing our override of ApplyConfiguration() does is call the base implementation. Dopo che questo metodo è stato completato, è possibile aggiungere in modo imperativo ServiceMetadataBehavior alla descrizione usando il codice imperativo seguente.Once this method completes, we can imperatively add the ServiceMetadataBehavior to the description using the following imperative code.

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

L'ultima operazione dell'override di ApplyConfiguration() è aggiungere l'endpoint di metadati predefinito.The last thing our ApplyConfiguration() override must do is add the default metadata endpoint. Per convenzione, viene creato uno endpoint di metadati per ciascun URI nella raccolta BaseAddresses del host del servizio.By convention, one metadata endpoint is created for each URI in the service host’s BaseAddresses collection.

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

Uso di un ServiceHost personalizzato in host indipendenteUsing a custom ServiceHost in self-host

Ora che è stata completata l'implementazione personalizzata di ServiceHost, è possibile usarlo per aggiungere il comportamento di pubblicazione dei metadati a qualsiasi servizio ospitando tale servizio all'interno di un'istanza di SelfDescribingServiceHost.Now that we have completed our custom ServiceHost implementation, we can use it to add metadata publishing behavior to any service by hosting that service inside of an instance of our SelfDescribingServiceHost. Nell'esempio di codice seguente viene illustrato come usarlo nello scenario di host indipendente.The following code shows how to use it in the self-host scenario.

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

L'host personalizzato legge comunque la configurazione dell'endpoint del servizio dal file di configurazione dell'applicazione, come se fosse stata usata la classe ServiceHost predefinita per ospitare il servizio.Our custom host still reads the service’s endpoint configuration from the application’s configuration file, just as if we had used the default ServiceHost class to host the service. Tuttavia, poiché è stata aggiunta la logica per abilitare la pubblicazione dei metadati all'interno dell'host personalizzato, non è più necessario abilitare in modo esplicito il comportamento di pubblicazione dei metadati nella configurazione.However, because we added the logic to enable metadata publishing inside of our custom host, we no longer must explicitly enable the metadata publishing behavior in configuration. L'approccio offre un vantaggio evidente quando si compila un'applicazione che contiene diversi servizi e si desidera abilitare la pubblicazione dei metadati su ognuno di essi senza riscrivere ripetutamente gli stessi elementi di configurazione.This approach has a distinct advantage when you are building an application that contains several services and you want to enable metadata publishing on each of them without writing the same configuration elements over and over.

Uso di un ServiceHost personalizzato in IIS e WASUsing a Custom ServiceHost in IIS or WAS

L'uso di un host del servizio personalizzato in scenari di host indipendente è semplice in quanto spetta fondamentalmente al codice dell'applicazione la responsabilità di creare e aprire l'istanza dell'host del servizio.Using a custom service host in self-host scenarios is straightforward, because it is your application code that is ultimately responsible for creating and opening the service host instance. In IIS o WAS ambiente di hosting, tuttavia, l'infrastruttura WCF è dinamicamente creazione di un'istanza dell'host del servizio in risposta ai messaggi in arrivo.In the IIS or WAS hosting environment, however, the WCF infrastructure is dynamically instantiating your service’s host in response to incoming messages. Gli host del servizio personalizzati possono essere usati anche in questo ambiente di hosting, ma richiedono del codice aggiuntivo nel modulo di un ServiceHostFactory.Custom service hosts can also be used in this hosting environment, but they require some additional code in the form of a ServiceHostFactory. Nel codice seguente è illustrato un derivato di ServiceHostFactory che restituisce istanze del SelfDescribingServiceHost personalizzato.The following code shows a derivative of ServiceHostFactory that returns instances of our custom 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);  
    }  
}  

Come è possibile vedere, l'implementazione di un ServiceHostFactory personalizzato è molto semplice.As you can see, implementing a custom ServiceHostFactory is very straightforward. Tutta la logica personalizzata risiede all'interno dell'implementazione ServiceHost; la factory restituisce un'istanza della classe derivata.All of the custom logic resides inside of the ServiceHost implementation; the factory returns an instance of the derived class.

Per usare una factory personalizzata con un'implementazione del servizio, è necessario aggiungere altri metadati al file con estensione svc del servizio.To use a custom factory with a service implementation, we must add some additional metadata to the service’s .svc file.

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

Qui è stato aggiunto un altro attributo Factory alla direttiva @ServiceHost al quale è stato passato come valore il nome del tipo CLR della factory personalizzata.Here we have added an additional Factory attribute to the @ServiceHost directive, and passed the CLR type name of our custom factory as the attribute’s value. Quando IIS o WAS riceve un messaggio per questo servizio, l'infrastruttura di hosting di WCF crea innanzitutto un'istanza di ServiceHostFactory e quindi creare un'istanza dell'host del servizio stesso chiamando ServiceHostFactory.CreateServiceHost().When IIS or WAS receives a message for this service, the WCF hosting infrastructure first creates an instance of the ServiceHostFactory and then instantiate the service host itself by calling ServiceHostFactory.CreateServiceHost().

Esecuzione dell'esempioRunning the Sample

Anche se questo esempio fornisce un'implementazione del client e del servizio completamente funzionante, l'obiettivo dell'esempio è illustrare come modificare il comportamento in fase di esecuzione di un servizio per mezzo di un host personalizzato eseguendo le operazioni seguenti:Although this sample does provide a fully-functional client and service implementation, the point of the sample is to illustrate how to alter a service’s run-time behavior by means of a custom host., do the following steps:

Per osservare l'effetto dell'host personalizzatoTo observe the effect of the custom host

  1. Aprire il file Web.config del servizio e osservare come non vi sia alcuna configurazione che abilita in modo esplicito i metadati per il servizio.Open the service’s Web.config file and observe that there is no configuration explicitly enabling metadata for the service.

  2. Aprire il file con estensione svc del servizio e osservare che il relativo @ServiceHost direttiva contiene un attributo Factory che specifica il nome di un ServiceHostFactory personalizzato.Open the service’s .svc file and observe that its @ServiceHost directive contains a Factory attribute that specifies the name of a custom ServiceHostFactory.

Per impostare, compilare ed eseguire l'esempioTo set up, build, and run the sample

  1. Assicurarsi di avere eseguito la procedura di installazione singola per gli esempi di Windows Communication Foundation.Ensure that you have performed the One-Time Setup Procedure for the Windows Communication Foundation Samples.

  2. Per compilare la soluzione, seguire le istruzioni in compilazione degli esempi di Windows Communication Foundation.To build the solution, follow the instructions in Building the Windows Communication Foundation Samples.

  3. Dopo aver compilato la soluzione, eseguire Setup.bat per configurare l'applicazione ServiceModelSamples in IIS 7.0IIS 7.0.After the solution has been built, run Setup.bat to set up the ServiceModelSamples Application in IIS 7.0IIS 7.0. La directory ServiceModelSamples verrà ora visualizzata come applicazione IIS 7.0IIS 7.0.The ServiceModelSamples directory should now appear as an IIS 7.0IIS 7.0 Application.

  4. Per eseguire l'esempio in una configurazione singola o tra computer, seguire le istruzioni in esegue gli esempi di Windows Communication Foundation.To run the sample in a single- or cross-machine configuration, follow the instructions in Running the Windows Communication Foundation Samples.

  5. Per rimuovere l'applicazione IIS 7.0IIS 7.0, eseguire Cleanup.bat.To remove the IIS 7.0IIS 7.0 application, run Cleanup.bat.

Vedere ancheSee Also

Procedura: ospitare un servizio WCF in IISHow to: Host a WCF Service in IIS