Einfaches WCF-Beispiel ohne komplizierte Config

Einfaches WCF-Beispiel ohne komplizierte Config

Unter anderem durch die Aktivität im myCSharp.de-Forum ist mir aufgefallen, dass viele Entwickler doch Probleme mit der Konfiguration von WCF-Diensten haben. Zugegeben; ich bin auch kein großer Fan des .NET-Konfigurationsframeworks. Es vereinfacht manches, aber es verkompliziert auch vieles, da unnötige Werte Verwirrung stiften.

Das finde ich wirklich schade. Denn dabei ist ein WCF-Service fundamental in wenigen Zeilen geschrieben. Ihr braucht dafür nur 3 Projekte:

<img src="/contents/2016/WCFCalcExample_Projektuebersicht.png"

Das Betreiben von WCF in Konsolen-Anwendungen nennt man "self-hosted". Entgegen dem zentralen Betreiben auf Webservern wie dem IIS, kann der WCF hier in einer Anwendung gehalten werden, um zum Beispiel eine Process-To-Process-Kommunikation zu ermöglichen; im Gegensatz zur klassischen IPC ist es hiermit jedoch einfacher auch Maschinen-übergreifend zu kommunizieren.

Beispielhaft habe ich hier ein WCF-Service (CalcService) erstellt, der die grundlegenste, bidirektionale Kommunikation darstellt: eine einfache Addition auf Server-Seite. Der Client liefert dafür die beiden Zahlen-Werte und erhält die Summe als Antwort.

Code Client:

// Client Source
class Program
{
    public const String Host = "net.tcp://localhost";
    public const Int32 Port = 31227;
    public const String ServiceName = "MathService";
 
    static void Main( string[ ] args )
    {
        // Address
        string svcAddress = Host + ":" + Port + "/" + ServiceName;
 
        // Binding
        NetTcpBinding tcpb = new NetTcpBinding( SecurityMode.Message );
        ChannelFactory<ICalcService> chFactory = new ChannelFactory<ICalcService>( tcpb );
 
        // Endpoint
        EndpointAddress epAddress = new EndpointAddress( svcAddress );
 
        // Create Channel
        ICalcService calcService = chFactory.CreateChannel( epAddress );
 
        Console.WriteLine( "Connected to service '" + svcAddress + "'." );
        var result = calcService.Add( 4, 5 );
 
        Console.WriteLine( "The result of 4+5 is '" + result + "'." );
 
        Console.WriteLine( "Press key to quit." );
        Console.ReadKey( );
 
        chFactory.Close( );
    }
}

Code Server:

class Program
{
    public const String Host = "net.tcp://localhost";
    public const Int32 Port = 31227;
    public const String ServiceName = "MathService";
 
    static void Main( string[ ] args )
    {
        string svcAddress = Host + ":" + Port + "/" + ServiceName;
        Uri svcUri = new Uri( svcAddress );
  
        using ( ServiceHost sh = new ServiceHost( typeof( CalcService ), svcUri ) )
        {
            // Binding
            NetTcpBinding tcpBinding = new NetTcpBinding( SecurityMode.Message );
 
            // Behavior
            ServiceMetadataBehavior behavior = new ServiceMetadataBehavior( );
            sh.Description.Behaviors.Add( behavior );
            sh.AddServiceEndpoint( typeof( IMetadataExchange ), MetadataExchangeBindings.CreateMexTcpBinding( ), "mex" );
 
            //Endpoint
            sh.AddServiceEndpoint( typeof( ICalcService ), tcpBinding, svcAddress );
 
            // Open
            sh.Open( );
 
            Console.WriteLine( "Service started '" + svcAddress + "' ...Press key to quit." );
            Console.ReadKey( );
 
            Console.WriteLine( "Quit. Press key to close." );
            Console.ReadKey( );
 
            // Close
            sh.Close( );
        }
     }
}

Client und Server müssen beide die Schnittstelle des Services kennen. Diese Logik ist in einem dritten Projekt ausgelagert.

Code Service

[ServiceContract]
public interface ICalcService
{
    [OperationContract]
    int Add( Int32 n1, Int32 n2 );
}
 
public class CalcService : ICalcService
{
    public int Add( Int32 n1, Int32 n2 )
    {
        return n1 + n2;
    }
}

Download / CodePlex

Der vollständige Quellcode ist unter CodePlex als WCFCalcExample verfügbar.