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.