Click here to Skip to main content
Click here to Skip to main content

Getting Started with RESTful WCF Powered by Nelibur

, 1 Jun 2014 MIT
Rate this:
Please Sign up or sign in to vote.
In this article, we'll see how to build reusable, stable and RESTful WCF service

Introduction

WCF is really powerful, but time after time for a new project, we've to create new but similar RESTful WCF service. In this article, we'll see how to build reusable RESTful message based WCF service powered by Nelibur. Nelibur - Message based web service framework on the pure WCF. Let's see how to get started with creating services using WCF powered by Nelibur.

Step 1: Create an Application

I'm going to use a Console application as WCF's ServiceHost for simplicity. So, during the first step, we just add a new empty Console project.

Step 2: Install Nelibur

The easiest way to install Nelibur is use NuGet package manager.

You can do the same through Package Manager Console.

Now we're ready to create the RESTful WCF message based service.

Step 3: Create WCF Service

For instance, we've standard WCF requirements:

Nelibur already contains default implementation JsonServicePerCall, as usual for RESTful WCF service we write:
internal class Program
{
    private static WebServiceHost _service;

    private static void Main()
    {
        _service = new WebServiceHost(typeof(JsonServicePerCall));
        _service.Open();

        Console.WriteLine("ShipTrackingService is running");
        Console.WriteLine("Press any key to exit\n");

        Console.ReadKey();
        _service.Close();
    }
} 

and add configuration section:

<system.serviceModel>
    <services>
        <service name="Nelibur.ServiceModel.Services.Default.JsonServicePerCall">
            <host>
                <baseAddresses>
                    <add baseAddress="http://localhost:9095/ShipTrackingService" />
                </baseAddresses>
            </host>
            <endpoint binding="webHttpBinding"
                        contract="Nelibur.ServiceModel.Contracts.IJsonService" />
        </service>
    </services>
</system.serviceModel> 

The service supports CRUD operations, i.e., following operations are available:

Message Delete(Message message);

void DeleteOneWay(Message message);

Message Get(Message message);

void GetOneWay(Message message);

Message Post(Message message);

void PostOneWay(Message message);

Message Put(Message message);

void PutOneWay(Message message);

Where "The Message class is fundamental to Windows Communication Foundation (WCF). All communication between clients and services ultimately results in Message instances being sent and received." (MSDN). I've removed WCF's attributes for simplicity, here is full version of the IJsonService.

Now let's implement a business logic.

Step 4: Implement Business Logic and Configure the Web Service

The service has to be able to do the following:

  • Add Ship
  • Get ship's location by ShipId
Adding a ship, the service receives an AddShipCommand and returns a ShipInfo.
public sealed class AddShipCommand
{
    public string ShipName { get; set; }
} 

The AddShipCommand is very simple and has only ShipName, the ShipInfo is very simple too.

public sealed class ShipInfo
{
    public Guid Id { get; set; }
    public string Name { get; set; }
} 

and finally the service receives ShipLocationQuery and returns ShipLocation:

Here are the contracts:

public sealed class ShipLocationQuery
{
    public Guid ShipId { get; set; }
} 
public sealed class ShipLocation
{
    public string Location { get; set; }
    public Guid ShipId { get; set; }
} 

Now we can create requests handler, all we have to do is implement appropriate IRequestOperation, in our case, a request handler looks like:

public sealed class ShipProcessor : IPost<AddShipCommand>,
                                    IGet<ShipLocationQuery>
{
    private static readonly Dictionary<Guid, Ship> _ships = new Dictionary<Guid, Ship>();

    public object Get(ShipLocationQuery request)
    {
        if (_ships.ContainsKey(request.ShipId))
        {
            return new ShipLocation
            {
                Location = "Sheldonopolis",
                ShipId = request.ShipId
            };
        }
        throw new WebFaultException(HttpStatusCode.BadRequest);
    }

    public object Post(AddShipCommand request)
    {
        var ship = new Ship(request.ShipName, Guid.NewGuid());
        _ships[ship.Id] = ship;
        return new ShipInfo
        {
            Id = ship.Id,
            Name = ship.Name
        };
    }
} 

Finally, we have to bind a request and appropriate request handler. Thus Nelibur knows where search appropriate CRUD method.

internal class Program
{
    private static WebServiceHost _service;

    private static void ConfigureService()
    {
        NeliburRestService.Configure(x =>
        {
            x.Bind<AddShipCommand, ShipProcessor>();
            x.Bind<ShipLocationQuery, ShipProcessor>();
        });
    }

    private static void Main()
    {
        ConfigureService();

        _service = new WebServiceHost(typeof(JsonServicePerCall));
        _service.Open();

        Console.WriteLine("ShipTrackingService is running");
        Console.WriteLine("Press any key to exit\n");

        Console.ReadKey();
        _service.Close();
    }
} 

We have completed with the service now. As you see, we can add any operation without changing WCF service.

The Client Consuming the Web Service

Any HTTP client can consume the web service, let's look on:

Fiddler as a HTTP Client

Here's the Post method with request and response:

A Get operation is similar and simple:

Rest Console as a HTTP Client

Here is a Post operation:

and the Response:

A Get operation will be the same, so let's look on the .NET HTTP client.

JsonServiceClient as a HTTP Client

Nelibur has the JsonServiceClient it's a wrapper over the HttpClient. The JsonServiceClient has the following methods:

public void Get(object request)
 
public TResponse Get<TResponse>(object request)
 
public Task GetAsync(object request)
 
public Task<TResponse> GetAsync<TResponse>(object request)
 
public void Post(object request)
 
public TResponse Post<TResponse>(object request)
 
public Task<TResponse> PostAsync<TResponse>(object request)
 
public Task PostAsync(object request)
 
public void Put(object request)
 
public TResponse Put<TResponse>(object request)
 
public Task PutAsync(object request)
 
public Task<TResponse> PutAsync<TResponse>(object request)

public void Delete(object request)
 
public TResponse Delete<TResponse>(object request)
 
public Task DeleteAsync(object request)
 
public Task<TResponse> DeleteAsync<TResponse>(object request) 

Here's the full self describing client's code:

internal class Program
{
    private static void Main()
    {
        var client = new JsonServiceClient(Settings.Default.ServiceAddress);
        var shipInfo = client.Post<ShipInfo>(new AddShipCommand { ShipName = "Star" });
        Console.WriteLine("The ship has added: {0}", shipInfo);

        var shipLocation = client.Get<ShipLocation>(new ShipLocationQuery { ShipId = shipInfo.Id });
        Console.WriteLine("The ship {0}", shipLocation);

        Console.ReadKey();
    }
}  

and execution results:

Here's the web service:

and the service client:

Further Reading

That's All Folks

I hope you enjoyed it, please take the time to post a comment. Thanks for reading the article.

License

This article, along with any associated source code and files, is licensed under The MIT License

Share

About the Author

Sergey Morenko
Software Developer (Senior)
Russian Federation Russian Federation
B.Sc. in Computer Science.
Follow on   Twitter   LinkedIn

Comments and Discussions

 
QuestionReal Sample Application Pinmemberkiquenet.com11-Jul-14 2:09 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141216.1 | Last Updated 2 Jun 2014
Article Copyright 2014 by Sergey Morenko
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid