KISS : WCF ServiceHost and ClientBase

This is meant to be a very simple overview of the servicehost creation in code and a clientbase creation in code.  And to help clarify how both use the configuration (it could be programmatic) ties into them.

Let’s take for instance that we have a very simple service.

[ServiceContract]
public interface IService
{
    [OperationContract(AsyncPattern=true, Action=*”)]
    IAsyncResult BeingResponse(Message message, AsyncCallback callback, object state);

    Message EndResponse(IAsyncResult result);
}

and an implementation of the service:

public class MyService : IService
{
    public IAsyncResult BeginResponse(Message message, AsyncCallback callback, object state)
    {
         return new CompletedAsyncResult(message);
    }

    public Message EndResponse(IAsyncResult r)
    {
        CompletedAsyncResult<Message> result = r
            as CompletedAsyncResult<Message>;
        return result.Data
    }
}

 

// Simple async result implementation.
  class CompletedAsyncResult<T> : IAsyncResult
  {
    T data;

    public CompletedAsyncResult(T data)
    { this.data = data; }

    public T Data
    { get { return data; } }

    #region IAsyncResult Members
    public object AsyncState
    { get { return (object)data; } }

    public WaitHandle AsyncWaitHandle
    { get { throw new Exception("The method or operation is not implemented."); } }

    public bool CompletedSynchronously
    { get { return true; } }

    public bool IsCompleted
    { get { return true; } }
    #endregion
  }

This is the service side.  Now, we want to go update our app.config (in this case, I’m running this in my test, so create or use existing config in your test project).  The endpoint is the key here, and commonly referred to as the ABC’s of WCF  (Address, Binding, Contract).

<system.serviceModel>
    <services>
        <service name="MyService">
            <endpoint
                name="MyService"
                address="net.tcp://localhost:4400/MyService"
                binding="netTcpBinding"
                contract="IService"
            />
        </service>
    </services>
    <bindings>
        <netTcpBinding>
            <binding name="netTcpBinding"
        </netTcpBinding>
    </bindings>
</system.serviceModel>

The service host will look to the service configuration file to find the setup for our IService contract and see that MyService is an implementation and use those settings.

 

So now let’s create a client to call into our service.  This can be done with a ChannelFactory, or a ClientBase.  For this example we’ll just use a ClientBase:

public class MyServiceClient : ClientBase<IService>, IService
{
    public IAsyncResult BeginResponse(Message message, AsyncCallback callback, object state)
    {
        IAsyncResult result = Channel.BeginResponse(message, callback, state);
        return result;
    }

    public Message EndResponse(IAsyncResult result)
    {
        return Channel.EndResponse(result);
    }
}

Pretty simple really, we implement the interface of our service contract and use the ClientBase.  The ClientBase handles the Channel.

Now let’s look at the configuration – since our example we will be hosting the service and client in same project, we can add the client configuration parts:

...
    <client>
        <endpoint
            name="MyService"
            address="net.tcp://localhost:4400/MyService"
            binding="netTcpBinding"
            contract="MyService"
        />
    </client>
</system.serviceModel>

ok, so returning to finish our test:

[TestMethod]
public void TestServiceWithClient()
{
    ServiceHost host = new ServiceHost(typeof(MyService));
    host.Open();

    Message message = Message.CreateMessage(MessageVersion.Default, "*", "Test Message");

    MyServiceClient proxy = new MyServiceClient();

    //just use inline callback...
    AsyncCallback completion = (result) =>
    {
        Message msg = proxy.EndResponse(result);
        Assert.AreEqual("Test Message", msg.GetBody<string>());
        proxy.Close();
    }

    proxy.Open();
    proxy.BeginResponse(message, completion, null);
    host.Close();
}

So there is an end to end self-hosted wcf service example.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s