Procedura: recuperare metadati e implementare un servizio conforme

Spesso i servizi non vengono progettati e implementati dalla stessa persona. Negli ambienti dove le applicazioni interoperative svolgono un ruolo importante, i contratti possono essere progettati o descritti in WSDL (Web Services Description Language) e uno sviluppatore deve implementare un servizio che sia conforme al contratto fornito. È anche possibile eseguire la migrazione di un servizio esistente a Windows Communication Foundation (WCF) ma mantenere il formato di collegamento. I contratti duplex richiedono inoltre ai chiamanti di implementare anche un contratto di callback.

In questi casi è necessario usare lo strumento ServiceModel Metadata Utility Tool (Svcutil.exe) (o un strumento equivalente) per generare un'interfaccia del contratto di servizio in un linguaggio gestito che possa essere implementata per soddisfare i requisiti del contratto. In genere lo strumento ServiceModel Metadata Utility Tool (Svcutil.exe) viene usato per acquisire un contratto di servizio usato con una channel factory o un tipo di client WCF nonché con un file di configurazione client che configura il binding e l'indirizzo corretti. Per usare il file di configurazione generato, è necessario modificarlo in un file di configurazione del servizio. Può inoltre essere necessario modificare il contratto di servizio.

Per recuperare dati e implementare un servizio conforme

  1. Usare lo strumento ServiceModel Metadata Utility Tool (Svcutil.exe) sui file di metadati o su un endpoint di metadati per generare un file di codice.

  2. Cercare la parte del file di codice di output che contiene l'interfaccia desiderata (nel caso siano presenti più interfacce) contrassegnata con l'attributo System.ServiceModel.ServiceContractAttribute. Nell'esempio di codice seguente vengono illustrate le due interfacce generate da ServiceModel Metadata Utility Tool (Svcutil.exe). La prima (ISampleService) è l'interfaccia del contratto di servizio che viene implementata per creare un servizio conforme. La seconda (ISampleServiceChannel) è un'interfaccia di supporto usata dal client che estende sia l'interfaccia del contratto di servizio che l'interfaccia System.ServiceModel.IClientChannel e che viene usata in un'applicazione client.

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(
      Namespace="http://microsoft.wcf.documentation"
    )]
    public interface ISampleService
    {
    
        [System.ServiceModel.OperationContractAttribute(
          Action="http://microsoft.wcf.documentation/ISampleService/SampleMethod",
          ReplyAction="http://microsoft.wcf.documentation/ISampleService/SampleMethodResponse"
        )]
        [System.ServiceModel.FaultContractAttribute(
          typeof(microsoft.wcf.documentation.SampleFault),
          Action="http://microsoft.wcf.documentation/ISampleService/SampleMethodSampleFaultFault"
        )]
        string SampleMethod(string msg);
    }
    
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    public interface ISampleServiceChannel : ISampleService, System.ServiceModel.IClientChannel
    {
    }
    
  3. Se la descrizione WSDL non specifica un'azione di replica per tutte le operazioni, è possibile che la proprietà ReplyAction dei contratti di operazione generati sia impostata sul carattere jolly (*). Rimuovere l'impostazione di questa proprietà. In caso contrario, quando vengono implementati i metadati del contratto di servizio, i metadati non possono essere esportati per tali operazioni.

  4. Implementare l'interfaccia in una classe e ospitare il servizio. Per un esempio, vedere Procedura: Implementare un contratto di servizio o vedere una semplice implementazione seguente nella sezione Esempio.

  5. Nel file di configurazione client generato dallo strumento ServiceModel Metadata Utility Tool (Svcutil.exe), modificare la sezione di configurazione <client> in una sezione di configurazione <servizi>. Per un esempio di file di configurazione dell'applicazione client generato, vedere la sezione "Esempio" seguente.

  6. Nella sezione di configurazione <servizi> creare un attributo name nella sezione <configurazione dei servizi> per l'implementazione del servizio.

  7. Impostare l'attributo name del servizio sul nome di configurazione da assegnare all'implementazione del servizio.

  8. Aggiungere gli elementi della configurazione endpoint che usano il contratto di servizio implementato alla sezione di configurazione del servizio.

Esempio

Nell'esempio di codice seguente viene illustrata la maggior parte di un file di codice generato eseguendo lo strumento ServiceModel Metadata Utility Tool (Svcutil.exe) sui file di metadati.

Il codice seguente include:

  • L'interfaccia del contratto di servizio che, quando implementata, è conforme ai requisiti del contratto (ISampleService).

  • L'interfaccia di supporto usata dal client che estende sia l'interfaccia del contratto di servizio che l'interfaccia System.ServiceModel.IClientChannel e che viene usata in un'applicazione client (ISampleServiceChannel).

  • La classe di supporto che estende System.ServiceModel.ClientBase<TChannel> e che deve essere usata in un'applicazione client (SampleServiceClient).

  • Il file di configurazione generato dal servizio.

  • Una semplice implementazione del servizio ISampleService.

  • Una conversione del file di configurazione lato client in una versione lato servizio.

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:2.0.50727.42
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

[assembly: System.Runtime.Serialization.ContractNamespaceAttribute("http://microsoft.wcf.documentation", ClrNamespace="microsoft.wcf.documentation")]

namespace microsoft.wcf.documentation
{
    using System.Runtime.Serialization;

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
    [System.Runtime.Serialization.DataContractAttribute()]
    public partial class SampleFault : object, System.Runtime.Serialization.IExtensibleDataObject
    {

        private System.Runtime.Serialization.ExtensionDataObject extensionDataField;

        private string FaultMessageField;

        public System.Runtime.Serialization.ExtensionDataObject ExtensionData
        {
            get
            {
                return this.extensionDataField;
            }
            set
            {
                this.extensionDataField = value;
            }
        }

        [System.Runtime.Serialization.DataMemberAttribute()]
        public string FaultMessage
        {
            get
            {
                return this.FaultMessageField;
            }
            set
            {
                this.FaultMessageField = value;
            }
        }
    }
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(
  Namespace="http://microsoft.wcf.documentation"
)]
public interface ISampleService
{

    [System.ServiceModel.OperationContractAttribute(
      Action="http://microsoft.wcf.documentation/ISampleService/SampleMethod",
      ReplyAction="http://microsoft.wcf.documentation/ISampleService/SampleMethodResponse"
    )]
    [System.ServiceModel.FaultContractAttribute(
      typeof(microsoft.wcf.documentation.SampleFault),
      Action="http://microsoft.wcf.documentation/ISampleService/SampleMethodSampleFaultFault"
    )]
    string SampleMethod(string msg);
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public interface ISampleServiceChannel : ISampleService, System.ServiceModel.IClientChannel
{
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class SampleServiceClient : System.ServiceModel.ClientBase<ISampleService>, ISampleService
{

    public SampleServiceClient()
    {
    }

    public SampleServiceClient(string endpointConfigurationName) :
            base(endpointConfigurationName)
    {
    }

    public SampleServiceClient(string endpointConfigurationName, string remoteAddress) :
            base(endpointConfigurationName, remoteAddress)
    {
    }

    public SampleServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
            base(endpointConfigurationName, remoteAddress)
    {
    }

    public SampleServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
            base(binding, remoteAddress)
    {
    }

    public string SampleMethod(string msg)
    {
        return base.Channel.SampleMethod(msg);
    }
}
<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_ISampleService" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                    useDefaultWebProxy="true">
                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                    <security mode="None">
                        <transport clientCredentialType="None" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="UserName" algorithmSuite="Default" />
                    </security>
                </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:8080/SampleService" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_ISampleService" contract="ISampleService"
                name="BasicHttpBinding_ISampleService" />
        </client>
    </system.serviceModel>
</configuration>
// Implement the service. This is a very simple service.
class SampleService : ISampleService
{
  public string SampleMethod(string msg)
  {
    Console.WriteLine("The caller said: \"{0}\"", msg);
    return "The service greets you: " + msg;
  }
}
<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_ISampleService" closeTimeout="00:01:00"
            openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
            allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
            maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
            messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
            useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
              maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None"
                realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <services>
      <service
          name="Microsoft.WCF.Documentation.SampleService">
        <endpoint address="http://localhost:8080/SampleService" binding="basicHttpBinding"
            bindingConfiguration="BasicHttpBinding_ISampleService" contract="Microsoft.WCF.Documentation.ISampleService"
            />
      </service>
    </services>
  </system.serviceModel>
</configuration>

Vedi anche