Archive

Archive for the ‘ServiceStack’ Category

Using ServiceStack with CodeFluent Entities

March 6, 2013 Leave a comment

In our last blog post we saw how to create a REST service layer using ASP .NET Web API and a CodeFluent Entities model.

Now we are going to use ServiceStack to expose HTTP web services (JSON and XML) from an existing CodeFluent Entities model.
ServiceStack is a REST Web Service Framework for .NET, it is an open source project that you can find here.
ServiceStack is based on a ‘modular’ architecture and it was built to be used in a simply way, no XML configuration and no code generation.
The ‘philosophy’ behind ServiceStack is to use strong-typed DTOs to define a web service API.
To illustrate this post we are going to use the Car Rental Sample project.

CarRental Sample  project

CarRental Sample project



We will add a Persistence producer (SQL Server 2012 for me) and a Business Object Model (BOM) producer.

Producers

Producers



ServiceStack can be used as a standalone solution or can be integrated on a MVC application, we are going to use it in an empty ASP .NET web application.

ASP .NET Web Application

ASP .NET Web Application



First of all we need to install ServiceStack in our ASP .NET web application project via nugget:

       PM> Install-Package ServiceStack

Now we need to register ServiceStack in our configuration (web.config), we want to host ServiceStack at the root path (‘/’) so we use this configuration:

<system.web>
  <compilation debug="true" targetFramework="4.5" />
  <httpRuntime targetFramework="4.5" />
  <httpHandlers>
    <add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*"/>
  </httpHandlers>
</system.web>

If you want register ServiceStack on a custom path to avoid conflicts with another web framework (eg. ASP .NET MVC) go here.

ServiceStack uses a particular structure for services, a service consists in:

  • A request DTO
  • A service implementation
  • A response DTO

We are going to create a service that handles CRUD operations for the Entity ‘CarGroup’ (you can add some instances to your model so we have some test data).

We start by creating the request DTOs:

[Route("/carGroup", "GET")]
public class GetAllCarGroupRequest : IReturn<CarGroupCollection> { }

[Route("/carGroup/{Id}", "GET")]
public class GetCarGroupRequest : IReturn<CarGroup>
{
    public int Id { get; set; }
}

[Route("/carGroup/{Id}", "DELETE")]
public class DeleteCarGroupRequest
{
    public int Id { get; set; }
}

As you can see we also have associated some routes to our requests.
For the create and update methods (POST and PUT) we will add the request configuration elsewhere because we want to use existing classes as requests (the CarGroup class that will be the object to add or update), we will see this further in this post.
Now we need to create our service and it operations. I will call my service ‘CarGroupService’ and it will inherit from the class ‘ServiceStack.ServiceInterface.Service’.

public class CarGroupService : ServiceStack.ServiceInterface.Service
{
}

ServiceStack will ‘match’ a request to an operation and associate HTTP actions (verbs) to the name of our operations, so our operations must follow some conventions:

public {ResponseDTO} {HTTPVerb}({RequestDTO} request)

Now we can create our operations.

To retrieve all our CarGroup objects:

public CarGroupCollection Get(GetAllCarGroupRequest request)
{
    CarGroupCollection carGroups = CarGroupCollection.LoadAll();
    return carGroups;
}

To retrieve one CarGroup by its id:

public CarGroup Get(GetCarGroupRequest request)
{
    CarGroup carGroup = CarGroup.Load(request.Id);
    if (carGroup == null)
    {
        throw new HttpError(System.Net.HttpStatusCode.NotFound, "Car Group not found");
    }
    return carGroup;
}

To add a new instance of CarGroup or to update an existing instance we will use a common method:

private HttpResult CreateUpdate(CarGroup carGroup)
{
    if (carGroup == null || !carGroup.Save())
    {
        return new HttpResult(System.Net.HttpStatusCode.BadRequest, "Error while saving.");
    }
    return new HttpResult(carGroup, System.Net.HttpStatusCode.OK);
}

And we will call this method for create (POST) and update (PUT) operations:

public HttpResult Post(CarGroup request)
{
    return CreateUpdate(request);
}
<br/>
public HttpResult Put(CarGroup request)
{
    return CreateUpdate(request);
}

Finally, to delete an instance of CarGroup:

public HttpResult Delete(DeleteCarGroupRequest request)
{
    CarGroup carGroup = CarGroup.Load(request.Id);
    if (carGroup != null && carGroup.Delete())
    {
        return new HttpResult(System.Net.HttpStatusCode.NoContent, "Car Group deleted");
    }
    return new HttpResult(System.Net.HttpStatusCode.NotFound, "Car Group not found");
}

We have created all the operations and their associated requests. Now we have to register our web service.

We start by creating an AppHost for our service that inherits from ServiceStack.WebHost.Endpoints.AppHostBase where we can configure our service if we need to, I will use the default configuration:

public class CarGroupAppHost : AppHostBase
{
    //Tell Service Stack the name of your application and where to find your web services
    public CarGroupAppHost() : base("CarGroup Web Services", typeof(CarGroupService).Assembly) { }

    public override void Configure(Container container)
    {
        Routes
            .Add<CarGroup>("/carGroup", "POST")
            .Add<CarGroup>("/carGroup", "PUT");
    }
}

We have added the route configuration for our create (POST) and update (PUT) operations.

Now in the Global.asax.cs file (you need to create it if it does not exist) we initialize our service host:

public class Global : System.Web.HttpApplication
{

    protected void Application_Start(object sender, EventArgs e)
    {
        new CarGroupAppHost().Init();
    }
}

We can found some information about our operations on the url ‘http://server/metadata’, in my case http://localhost:4305/metadata.

Service metadata information

Service metadata information



And that is all, we can test now our service, we will use a Console application.

For example to retrieve all our Car Groups:

string uri = "http://localhost:4305/carGroup";
HttpWebRequest request = HttpWebRequest.CreateHttp(uri);
request.Accept = "application/json";//we only accept JSON
request.Method = "GET";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
    Console.WriteLine(response.StatusCode);
    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
    {
        string result = reader.ReadToEnd();
        Console.WriteLine(result);
    }
}

And we get:

Get all data service result

Get all data service result



Let’s now test the creation of a new CarGroup:

string uri = "http://localhost:4305/carGroup";
HttpWebRequest request = HttpWebRequest.CreateHttp(uri);
request.Accept = "application/json"; //we only accept JSON
request.Method = "POST";
request.ContentType = "application/json; charset=UTF-8";//we will send JSON

string bodyData = "{\"Name\":\"Super Sport\",\"Category\":\"Mega Sport\"}";

//----- writing data in to the request --------------
request.ContentLength = bodyData.Length;
using (StreamWriter requestWritter = new StreamWriter(request.GetRequestStream()))
{
    requestWritter.Write(bodyData);
}

//----- reading the response
string result = "";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
    Console.WriteLine(response.StatusCode);
    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
    {
        result = reader.ReadToEnd();
        Console.WriteLine(result);
    }
}

We have just seen how CodeFluent Entities can be easily integrated to ServiceStack.

ServiceStack is a very powerful framework to write Web APIs, you can find more information about ServiceStack and all the features it provides here.

Regards.

Pablo Fernandez Duran