WCF Services Using HTTP and TCP Endpoints

1. Add the System.ServiceModel namespace and create an interface which describes your service class:

    using System.ServiceModel;

    [ServiceContract(Namespace = "http://my.unique.namespace.com/MyService")]
    public interface IMyService
    {
        // Definition of my methods

        [OperationContract]
        string MyStringMethod(string myStringArg);

        [OperationContract]
        MyComplexOne MyComplexMethod(MyComplexOne myComplexArg);
    }
The interface is defined with the [ServiceContract] decorator (with namespace) and the individual methods decorated with [OperationContract], both from the ServiceModel assembly, setting these up as WCF service contract definitions.
2. If you need to pass complex objects (as with the second contract above), you need to separately define the complex object in a serializable DataContract object, with the appropriate decorators from the Runtime.Serialization namespace. This can be done in the same interface file for convenience:

    using System.Runtime.Serialization;

    [DataContract(Namespace = "http://my.unique.namespace.com/MyService")]
    [Serializable]
    public class MyComplexOne
    {
        bool boolValue = true;
        string stringValue = "";

        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }
3. Now we can implement the service methods in the previous interface in a service class inheriting the interface.

    public class MyServiceClass : IMyService
    {
        public string MyStringMethod(string value)
        {
            return string.Format("You entered: {0}", value);
        }

        public MyComplexOne MyComplexMethod(MyComplexOne composite)
        {
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }
    }
These two methods are noddy ones, but they just demonstrate the concrete implmentation of the two methods.
4. All other configuration now appears in web.config (or App.config for other types of project). WCF service projects will have the following sections in the config file (collapsed for clarity)

   <system.serviceModel>
     <bindings>...</bindings>
     <services>...</services>
     <behaviors>...</behaviors>
   </system.serviceModel>
We'll go into the details of each section separately, but the summary of the sections is as follows:

<bindings> Contains the types of endpoints available, e.g. HTTP or TCP, etc.
<services> Contains the services e.g. MyService and picks a binding
<behaviors> Contains the properties of each service, e.g timeouts, concurrent connections, etc.

5. Depending on the type of bindings required, you will have one or more of the following sections within the <bindings> section :

FOR TCP (with standard settings):

      <netTcpBinding>
         <binding name="MyTcpBinding" maxReceivedMessageSize="650000">
            <security mode="None" />
         </binding>
      </netTcpBinding>
FOR HTTP (including legacy webservice):

      <basicHttpBinding>
         <binding
             name="MyHttpBinding"
             maxReceivedMessageSize="650000"
             openTimeout="00:10:00"
             receiveTimeout="00:10:00"
             sendTimeout="00:10:00" />
      </basicHttpBinding>
FOR MEX (metadata exchange - usually turned off anyway, so not required):

      <mexTcpBinding>
         <binding name="mexTcpBinding" />
      </mexTcpBinding>
      <mexHttpBinding>
         <binding name="mexHttpBinding" />
      </mexHttpBinding>
There are several standard built-in bindings included with WCF used for various sorts of integration - these are : BasicHttpBinding, WSHttpBinding, WSDualHttpBinding, WSFederationHttpBinding, MsmqIntegrationBinding, NetMsmqBinding, NetNamedPipeBinding, NetPeerTcpBinding, NetTcpBinding but usually only the http and tcp are used. You can define a custom binding which can be a derivative or combination of any other standard bindings, an example being:
      <customBinding>
         <binding
             name="CustomTcpBinding"
             maxReceivedMessageSize="650000"
             openTimeout="00:10:00"
             receiveTimeout="00:10:00"
             sendTimeout="00:10:00" >
             <tcpTransport
                 maxReceivedMessageSize="650000"
                 maxPendingConnections="20"
                 listenBacklog="20" >
                 <connectionPoolSettings
                     groupName="default"
                     leaseTimeout="00:05:00"
                     idleTimeout="00:02:00"
                     maxOutboundConnectionsPerEndpoint="100" />
              </tcpTransport>
            </binding>
      </customBinding>

6. For each separate WCF service, you will have one of the following sections within the <services> section :

  <service behaviorConfiguration="MyNameSpace.MyServiceBehavior" name="MyNameSpace.MyServiceName">
     <endpoint
        address="service"
        binding="basicHttpBinding"
        bindingConfiguration="MyHttpBinding"
        name="MyHttpEndpoint"
        contract="MyNameSpace.IMyService">
           <identity>
              <dns value="localhost" />
           </identity>
     </endpoint>
     <!--<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="mexTcpBinding" name="mexEndPoint" contract="IMetadataExchange" />-->
     <host>
        <baseAddresses>
           <add baseAddress="http://localhost:1016/MyService/" />
        </baseAddresses>
     </host>
  </service>
The service behaviorConfiguration defines a behavior section (to be described in the next bit)
The endpoint address is always 'service'
The endpoint binding is one of the built-in binding types given above
The endpoint bindingConfiguration is our named binding section from above
The endpoint contract is the interface described in step 1 above
The host baseAddress is the URI and port the service will run on (port should be as per IIS config)

For TCP endpoints, the baseAddress is given in the net.tcp format:
    <baseAddresses>
       <add baseAddress="net.tcp://localhost:1016/MyService/" />
    </baseAddresses>
7. For each behavior section referred in the services section above we need one of these in the <behaviors> section (all inside a serviceBehaviors containing node):

   <serviceBehaviors>
      <behavior name="MyNameSpace.MyServiceBehavior">
         <serviceMetadata httpGetEnabled="true" />
         <serviceDebug includeExceptionDetailInFaults="true" />
         <serviceThrottling maxConcurrentCalls="500" />
      </behavior>
   </serviceBehaviors>
8. You should be able to build, open a browser and navigate to the service.

The service page will be displayed (unless you had turned serviceMetadata : httpGetEnabled to false in the behavior section). This shows you how to get the WSDL and how to write a client, which we'll do in the next section.

9. You can run the svcutil within a Visual Studio command window to produce a sample client consumer class and an appropriate configuration section:

    svcutil.exe http://localhost:3238/MyService.svc?wsdl
And this will produce the following files:
    MyService.cs
    output.config
Start a new project, which will be the consumer of your service, and drop the .cs file into the App_Code or main folder, and the configuration in web.config or App.config.
10. The .cs file contains everything your client will need to access the remote methods and any associated classes and interfaces. The code is autogenerated, so it's not worth going through in immense detail, but in summary, it contains:

    namespace my.unique.@namespace.com.MyService
    {
       public partial class MyComplexOne : object, System.Runtime.Serialization.IExtensibleDataObject
       {
         ...
       }
    } 
This is the definition of any complex data objects described in your original DataContract, and lets you define local variables of this type, which can be used as arguments or return types from the services. Note: the namespace given to it is from the original decoration in the DataContract back on the service.
    public interface IMyService
    {
      ...
    }
This is a local copy of the service interface defined back in the service itself, as a 'contract' for the client to use.
    public partial class MyServiceClient : System.ServiceModel.ClientBase<IMyService>, IMyService
    {
      ...
    }
This is a proxy class for the remote services, which uses the service assemblies to convey the messages to the remote server using the appropriate transport and endpoints.
11. The configuration file contains a <system.serviceModel> section which should be copied into the appropriate web.config or App.config. An example autogenerated section would look like:

    <system.serviceModel>
       <bindings>
          <basicHttpBinding>
             <binding name="MyHttpEndpoint" 
                      closeTimeout="00:01:00"              
                      openTimeout="00:01:00"              
                      receiveTimeout="00:10:00"              
                      sendTimeout="00:01:00"              
                      allowCookies="false"              
                      bypassProxyOnLocal="false"              
                      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:1016/MyService.svc/service"
                 binding="basicHttpBinding"
                 bindingConfiguration="MyHttpEndpoint"
                 contract="IMyService"
                 name="MyHttpEndpoint"  />
       </client>
    </system.serviceModel>
Two things to note: Firstly, the address of the remote service can be changed here. Secondly, there is no sign of the TCP endpoint we had in our service. This is because the MyService service was configured to use the HTTP endpoint, and when svcutil is run, it looks at the current configuration of the service and provides a stub for that, it doesn't provide config sections for all available endpoints, only the ones being used by the service. If we wanted to switch to TCP in future, we would need to re-wire the server end to use the TCP endpoint, then re-run svcutil to generate the appropriate config section (the .cs file would remain the same) - by copying the TCP binding section into the config, we would be able to switch between HTTP and TCP at each end.
12. In our new client class, we can instantiate our remote service, define local variables of ComplexType, and call all available methods on the remote service:


  using my.unique.@namespace.com.MyService;

        MyServiceClient localMyService = new MyServiceClient();

        MyComplexOne localComplexOne = new MyComplexOne();
        localComplexOne = localMyService.MyComplexMethod(localComplexOne);

        string localResult = localMyService.MyStringMethod("hello");

Note the remote complex object types have the remote namespace, so we need the using line, or fully qualify these objects.
And that is how you do WCF services using HTTP and TCP!