Understanding Generated Client Code

The ServiceModel Metadata Utility Tool (Svcutil.exe) generates client code and a client application configuration file for use in building client applications. This topic provides a tour of generated code examples for standard service contract scenarios. For more information about building a client application using the generated code, see WCF Client Overview.

Overview

If you use Visual Studio to generate Windows Communication Foundation (WCF) client types for your project, you typically do not need to examine the generated client code. If you are not using a development environment that performs the same services for you, you can use a tool such as Svcutil.exe to generate client code and then use that code to develop your client application.

Because Svcutil.exe has a number of options that modify the generated type information, this topic does not discuss all scenarios. However, the following standard tasks involve locating generated code:

  • Identifying service contract interfaces.

  • Identifying the WCF client class.

  • Identifying data types.

  • Identifying callback contracts for duplex services.

  • Identifying the helper service contract channel interface.

Finding Service Contract Interfaces

To locate the interfaces that model service contracts, search for interfaces that are marked with the System.ServiceModel.ServiceContractAttribute attribute. Often this attribute can be difficult to locate with a quick read due to the presence of other attributes and the explicit properties set on the attribute itself. Remember that the service contract interface and the client contract interface are two different types. The following code example shows the original service contract.

[ServiceContractAttribute(
  Namespace = "http://microsoft.wcf.documentation"
)]
public interface ISampleService
{
  [OperationContractAttribute]
  [FaultContractAttribute(typeof(microsoft.wcf.documentation.SampleFault))]
  string SampleMethod(string msg);
}

The following code example shows the same service contract as generated by Svcutil.exe.

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

You can use the generated service contract interface along with the System.ServiceModel.ChannelFactory class to create a WCF channel object with which to invoke service operations. For more information, see How to: Use the ChannelFactory.

Finding WCF Client Classes

To locate the WCF client class that implements the service contract you want to use, search for an extension of System.ServiceModel.ClientBase<TChannel>, where the type parameter is the service contract interface that you previously located and that extends that interface. The following code example shows the ClientBase<TChannel> class of type ISampleService.

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

You can use this WCF client class by creating a new instance of it and calling the methods it implements. Those methods invoke the service operation with which it is designed and configured to interact. For more information, see WCF Client Overview.

Note

When SvcUtil.exe generates a WCF client class, it adds a DebuggerStepThroughAttribute to the client class that prevents debuggers from stepping through the WCF client class.

Finding Data Types

To locate data types in the generated code, the most basic mechanism is to identify the type name specified in a contract and search the code for that type declaration. For example, the following contract specifies that the SampleMethod can return a SOAP fault of type microsoft.wcf.documentation.SampleFault.

[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);

Searching for SampleFault locates the following type declaration.

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

In this case the data type is the detail type thrown by a specific exception on the client, a FaultException<TDetail> where the detail type parameter is microsoft.wcf.documentation.SampleFault. For more information about data types, see Specifying Data Transfer in Service Contracts. For more information about handling exceptions in clients, see Sending and Receiving Faults.

Finding Callback Contracts for Duplex Services

If you locate a service contract for which the contract interface specifies a value for the ServiceContractAttribute.CallbackContract property, then that contract specifies a duplex contract. Duplex contracts require the client application to create a callback class that implements the callback contract and pass an instance of that class to the System.ServiceModel.DuplexClientBase<TChannel> or System.ServiceModel.DuplexChannelFactory<TChannel> used to communicate with the service. For more information about duplex clients, see How to: Access Services with a Duplex Contract.

The following contract specifies a callback contract of type SampleDuplexHelloCallback.

[System.ServiceModel.ServiceContractAttribute(
  Namespace="http://microsoft.wcf.documentation",
  ConfigurationName="SampleDuplexHello",
  CallbackContract=typeof(SampleDuplexHelloCallback),
  SessionMode=System.ServiceModel.SessionMode.Required
)]
public interface SampleDuplexHello
{
  [System.ServiceModel.OperationContractAttribute(
      IsOneWay=true,
      Action="http://microsoft.wcf.documentation/SampleDuplexHello/Hello"
    )]
    void Hello(string greeting);
  }
    <System.ServiceModel.OperationContractAttribute(IsOneWay:=True, _
        Action:="http://microsoft.wcf.documentation/SampleDuplexHello/Hello")> _
    Sub Hello(ByVal greeting As String)
End Interface 'SampleDuplexHello

Searching for that callback contract locates the following interface that the client application must implement.

  [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public interface SampleDuplexHelloCallback
{
  [System.ServiceModel.OperationContractAttribute(
      IsOneWay=true,
      Action="http://microsoft.wcf.documentation/SampleDuplexHello/Reply"
    )]
    void Reply(string responseToGreeting);
  }
<System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")>  _
Public Interface SampleDuplexHelloCallback
    <System.ServiceModel.OperationContractAttribute( _
        IsOneWay:=True, _
        Action:="http://microsoft.wcf.documentation/SampleDuplexHello/Reply")> _
    Sub Reply(ByVal responseToGreeting As String)
End Interface 'SampleDuplexHelloCallback

Finding Service Contract Channel Interfaces

When using the ChannelFactory class with a service contract interface, you must cast to the System.ServiceModel.IClientChannel interface to explicitly open, close, or abort the channel. To make it easier to work with, the Svcutil.exe tool also generates a helper interface that implements both the service contract interface and IClientChannel to enable you to interact with the client channel infrastructure without having to cast. The following code shows the definition of a helper client channel that implements the preceding service contract.

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

See also