Mono WCF Advent Day 2: Hello WCF

| 4 Comments | No TrackBacks

OK, Day 1 was spent mostly on the introduction. Today I'll start with the simplest pair of a client and a server. I don't explain how to use Mono here. There would be a lot of introductions on Mono itself, so revisit here once you got to know how-tos.

Examples

I start with a simple C# example pair of a client and a service:

// Client
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;

[ServiceContract]
public interface IHelloService
{
  [OperationContract]
  string Greet (string name);
}

public class HelloClient : ClientBase<IHelloService>, IHelloService
{
  public HelloClient (Binding binding, EndpointAddress address)
    : base (binding, address)
  {
  }

  public string Greet (string name)
  {
    return Channel.Greet (name);
  }
}

public class Test
{
  public static void Main (string [] args)
  {
    string name = args.Length > 0 ? args [0] : "Anonymous Joe";
    var binding = new BasicHttpBinding ();
    var address = new EndpointAddress ("http://localhost:8080");
    var client = new HelloClient (binding, address);
    Console.WriteLine (client.Greet (name));
  }
}
// Service
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;

[ServiceContract]
public interface IHelloService
{
  [OperationContract]
  string Greet (string name);
}

public class HelloService : IHelloService
{
  public string Greet (string name)
  {
    return "hola, " + name;
  }
}

public class Test
{
  public static void Main (string [] args)
  {
    var binding = new BasicHttpBinding ();
    var address = new Uri ("http://localhost:8080");
    var host = new ServiceHost (typeof (HelloService));
    host.AddServiceEndpoint (
      typeof (IHelloService), binding, address);
    host.Open ();
    Console.WriteLine ("Type [CR] to stop...");
    Console.ReadLine ();
    host.Close ();
  }
}

Now, open two new text files, client.cs and service.cs, for each of above. To create executables, compile them to exes:

$ gmcs client.cs -pkg:wcf
$ gmcs service.cs -pkg:wcf

Here I used a mono-specific command line option: -pkg:wcf. -pkg option is used to give a set of compiler options. It is based on pkgconfig system, so you can see what it gives by running "pkg-config --libs wcf" . Our C# compilers does not automatically add references to non-core assemblies, so you have to add them manually like "gmcs -r:System.ServiceModel.dll foo.cs" unless you use this -pkg option.

Once you got client.exe and service.exe, run them in order (you had better open two console windows or tabs):

$ mono service.exe
Type [CR] to stop...
$ mono client.exe  # without arguments
hola, anonymous joe

$ mono client.exe eno # with an argument
hola, eno

Contract and client

The client example is a typical WCF client generated by either a "Service Reference" in Visual Studio or "svcutil.exe" tool in Windows SDK.

In the code, it first has a "contract" interface IHelloService, which is also included in the service code. The interface type is attributed by [ServiceContract] and its Greet() method is attributed by [OperationContract]. They make up the "service contract".

With an identical contract, it is possible for a client and a server to communicate with each other, as long as they share "address" and "binding". The "address" here is an EndpointAddress, or a Uri which point to "http://localhost:8080" here. The "binding" here is BasicHttpBinding. I don't explain about them right now.

A "Contract" is realized by ClientBase<T> class at client side, and ServiceHost class at service side (it is not most precise explanation, but most of WCF consumers can live with it).

ClientBase<T> is an abstract class and used to be derived with the contract interface itself (see how HelloClient class is declared). To complete the derived class, it just has to implement the contract interface, and it can just use the "Channel" property, which is of the interface type itself (it is automagically generated internally).

Service and communication

While you don't have to "implement" the interface by yourself (well, HelloClient implements Greet(), but there isn't any of your logic code; you just delegated it to the Channel), you have to implement the actual processing of Greet() operation in your service code. The example above hence implements it, by just returning "Hello, " + name.

Once you implemented your contract, then create a ServiceHost object by passing the type of your implementation class. You will then need another magic line of code: AddServiceEndpoint() indicates that a specific contract interface in the implementation class (the service class may implement more than one contract interfaces) is bound to a specific "binding" and an "address" again.

Now the service is ready to run. Open() indicates that the service instance to serve requests. It internally starts a service listener loop threads to process incoming client requests, which are independent of the Main() thread (you can stop the ServiceHost at any time by calling Close() method).

While the service is open, try running client.exe. It internally creates a SOAP request (which is what BasicHttpBinding creates) and sends it to "http://localhost:8080" (the endpoint address), and processes the response received from the service, where the response is a SOAP message that includes "Hello, " + input.

No TrackBacks

TrackBack URL: http://veritas-vos-liberabit.com/monogatari/mt-tb.cgi/85

4 Comments

Great example, thanks!

Hello,
I write the same code with Visual Studio and i tried
to deploy this code on Open Suse with Mono Tools for Visual studio
but it doesn't Work because Mono send me this Exception : The requested feature is not implemented.

I just need to Know if i can deploy WCF apps from Visual Studio to Mono, if you Have URLS or simples Demos, i would be pleasure if help me.

Thanks

From your entire comment, I could only guess you are using some not-implemented stuff in anywhere possible (WCF stuff, elsewhere in mono, VS tool or even your application). Try MoMA tool to see if your application depends on something that throws NotImplementedException.

Brilliant, thank you for this.

Leave a comment