Recommended Servicestack API Structure

Recommended ServiceStack API Structure

Firstly "Best" solution is a fairly subjective term. I'll generally aim for DRY, re-usable, performant solutions that promotes the least effort, friction and chattiness, whilst others may define "Best" in how closely it follows the principles of REST. So you will get varied responses depending on what the goals are. I can only offer how I would approach it.

ServiceStack service implementations are de-coupled from their custom routes

One thing to keep in mind is how you define and design your services in ServiceStack are fairly de-coupled in how you expose them, since you can expose your services under any custom route. ServiceStack encourages a message-based design so you should give each operation a distinct message.

Use a logical / hierarchical Url structure

I'd use a logical Url structure that I aim to represent the identifier of a noun, which is hierarchically structured, i.e. the parent path categorizes your resource and gives it meaningful context. So in this case if you wanted to expose Events and reviews my inclination is to go with following url structure:

/events             //all events
/events/1 //event #1
/events/1/reviews //event #1 reviews

Each of these resource identifiers can have any HTTP Verb applied to them

Implementation

For the implementation I generally follow a message-based design and group all related operations based on Response type and call context. For this I would do something like:

[Route("/events", "GET")]
[Route("/events/category/{Category}", "GET")] //*Optional top-level views
public class SearchEvents : IReturn<SearchEventsResponse>
{
//Optional resultset filters, e.g. ?Category=Tech&Query=servicestack
public string Category { get; set; }
public string Query { get; set; }
}

[Route("/events", "POST")]
public class CreateEvent : IReturn<Event>
{
public string Name { get; set; }
public DateTime StartDate { get; set; }
}

[Route("/events/{Id}", "GET")]
[Route("/events/code/{EventCode}", "GET")] //*Optional
public class GetEvent : IReturn<Event>
{
public int Id { get; set; }
public string EventCode { get; set; } //Alternative way to fetch an Event
}

[Route("/events/{Id}", "PUT")]
public class UpdateEvent : IReturn<Event>
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime StartDate { get; set; }
}

And follow a similar pattern for Event reviews

[Route("/events/{EventId}/reviews", "GET")]
public class GetEventReviews : IReturn<GetEventReviewsResponse>
{
public int EventId { get; set; }
}

[Route("/events/{EventId}/reviews/{Id}", "GET")]
public class GetEventReview : IReturn<EventReview>
{
public int EventId { get; set; }
public int Id { get; set; }
}

[Route("/events/{EventId}/reviews", "POST")]
public class CreateEventReview : IReturn<EventReview>
{
public int EventId { get; set; }
public string Comments { get; set; }
}

The implementation should be fairly straight forward based on these messages, which (depending on code-base size) I would organize in 2 EventsService and EventReviewsService classes. I should note that I use pluralization for Service Request DTO names myself to avoid clashing with data models of the same name.

Although I've separated UpdateEvent and CreateEvent here, I will sometimes will merge them into a single idempotent StoreEvent operation if the use-case permits.

Physical Project Structure

Ideally the root-level AppHost project should be kept lightweight and implementation-free. Although for small projects with only a few services it's ok for everything to be in a single project and to simply grow your architecture when and as needed.

For medium-to-large projects we recommend the physical structure below which for the purposes of this example we'll assume our Application is called EventMan.

The order of the projects also show its dependencies, e.g. the top-level EventMan project references all sub projects whilst the last EventMan.ServiceModel project references none:

- EventMan
AppHost.cs // ServiceStack ASP.NET Web or Console Host Project

- EventMan.ServiceInterface // Service implementations (akin to MVC Controllers)
EventsService.cs
EventsReviewsService.cs

- EventMan.Logic //For larger projs: pure C# logic, data models, etc
IGoogleCalendarGateway //E.g of a external dependency this project could use

- EventMan.ServiceModel //Service Request/Response DTOs and DTO types
Events.cs //SearchEvents, CreateEvent, GetEvent DTOs
EventReviews.cs //GetEventReviews, CreateEventReview
Types/
Event.cs //Event type
EventReview.cs //EventReview type

With the EventMan.ServiceModel DTO's kept in their own separate implementation and dependency-free dll, you're freely able to share this dll in any .NET client project as-is - which you can use with any of the generic C# Service Clients to provide an end-to-end typed API without any code-gen.


Update

  • This recommended project structure is now contained in all ServiceStackVS' VS.NET Templates.

  • The Simple Customer REST Example has a small self-contained, real-world example of creating a simple REST Service utilizing an RDBMS.

What is the appropriate project architecture for large scale ServiceStack/.NET projects?

This contains too many broad questions to be able to answer in any depth, Questions should not have multiple disjointed questions covering different topics, you should split this up into multiple focused questions so it's clear what the question is and the answer that it's expecting.

I'd first recommend going through the Designing APIs section in ServiceStack's documentation which walks through designing APIs with ServiceStack.

Pay special attention to Software complexity, goals of Services and important role of DTOs as it covers a lot of what you should the thinking about when creating Services. E.g. If you use a code-first POCO Micro ORM like OrmLite you can re-use the Data Models in your DTOs, ViewModels, Caching Providers, etc. But when you need to you can use ServiceStack's built-in AutoMapping to easily map between models <-> DTOs. Either way try to avoid having multiple artificial layers and different models in each layer which is a large source of unnecessary friction.

It also highlights that you should be looking to reduce any unnecessary layers/patterns/etc when possible as each time you add a layer you're adding artificial friction so make sure every Layer you add serves a purpose and you can see the value they each add. E.g. I'd recommend against having multiple fine-grained repositories, I'll generally have a repository to cover an entire sub-system of related functionality and would highly recommend against mechanically creating fine-grained repositories based on some arbitrary rule that's not related to your domain, e.g. per Table.

You only need C# interfaces if you have multiple implementations or want to write tests mocking them.

ServiceStack encourages coarse-grained Message-based Services so instead of client-specific fine-grained RPC Services, try to design generic, reusable, batchful Services that minimize forcing clients to perform multiple, dependent I/O Services and send data clients need in a single Service response when it's cohesive to that request.

ServiceStack's Physical Project Structure is already implemented in most of ServiceStackVS VS.NET Templates so I'd recommend starting a new project using the most appropriate ServiceStackVS template. E.g. {Project}.ServiceInterface holds the Service Implementation whereas {Project}.ServiceModel holds the DTO's in a impl-free Project so the types can be reused.

By just maintaining DTOs in a separate ServiceModel project, it eliminates the friction for clients which can reuse the Typed DTOs with any ServiceStack C#/.NET Client to enable an end-to-end Typed API without effort.

Instead of sharing your ServiceModel project, clients can also use ServiceStack's Add ServiceStack Reference feature to import all Types for a remote Service which it can use with the C# Clients to enable a Typed API. To see how and why this works live checkout Add ServiceStack Reference on Gistlyn which lets you call any remote ServiceStack Service from a browser.

Developing a servicestack API from a json structure

What you need is not an API but a way to deserialize the JSON structure into a .NET class instance. You can do this with a number of serializers. Last time I saw, servicestack provided its own, there is also the very popular JSON.NET library.

As a rule of thumb:

  • a json object becomes a .NET class
  • a value becomes a property
  • a list becomes a .NET array or List.

To get you started, look at this:

class Whatevs {
Population population { get; set; }
List<Staff> staffs { get; set; }
}

You still need to fill in the blanks for the classes Population and Staff.

ServiceStack OrmLite - Physical Project Structure

OrmLite works with dependency-free POCO (Plain old C# Objects) which can be maintained anywhere as you see fit depending on the complexity of your solution.

This answer explores the simplest approach of where you can reuse your DTOs for your OrmLite models. When your needs diverge and you need to separate your DTOs and your Data Models, e.g. more fields were added to the RDBMS table than you want to return, you can maintain them in your ServiceInterface implementation project.

When the complexity of your solution grows and you have other components that needs access to the Data Models independently from your Service implementation than you can move your OrmLite models in its own DataModel project. Note: Your "model" projects should have the minimum dependencies required and all your logic projects should be depending on them and not the other way around.

In what order are the ServiceStack examples supposed to be grokked?

ServiceStack example projects aren't supposed to be consumed in any particular order, they're just different examples illustrating what you can do with ServiceStack.

Setting up ServiceStack

If you want to know how to create and setup a ServiceStack service the easiest way is to Create your project with ServiceStackVS VS.NET extension, there's also the Getting Started section on the wiki and the Hello World example project can give you a good idea of what ServiceStack enables. This gist is another a good example of what you get with just 1 C# .cs class in ServiceStack.

Designing and structuring a REST API

If you're comfortable with setting up and configuring ServiceStack I've provided a detailed overview of how I'd go about designing a REST API inc. the physical layout and code structure in this earlier answer.

Example Projects, Use-cases and Live Demos

Otherwise the example projects and live demos are good reference examples showing how ServiceStack can be used to power individual use-cases. So you would basically just explore the ones that are similar to your use-case. I'll provide a description of each

Email Contacts

The EmailContacts repository is a new guidance available that walks through the recommended setup and physical layout structure of typical medium-sized ServiceStack projects, including complete documentation of how to create the solution from scratch, whilst explaining all the ServiceStack features it makes use of along the way. It also shows how to make use of ServiceStack's new Rabbit MQ Support.

HTTP Benchmarks

The HttpBenchmarks repository allows you to upload Apache HTTP Benchmarks to visualize and analyze their results. It's an example of a "Social website" supporting Twitter, Facebook, Google and LinkedIn OAuth providers, Registration of new Users, Personalized home page, Creation of User-defined top-level routes (e.g. twitter.com/userslug). It also walks through its integration with Glimpe, DotNetOpenAuth, FineUploader, DotNetZip and Highcharts.js. Hosting and deploying to AWS, Configuration of SSL certificates and enable forced redirects to https.

Chat

Chat takes you through how to build a rich Single Page Chat WebApp using Server push notifications enabled by ServiceStack's integrated support for Server Sent Events. It walks through the Server Event client bindings in /js/ss-utils.js to provide a number of flexible options for invoking pre-defined functionality in existing web apps, which it uses to show how to remote-control other users Chat Window with minimal effort.

Razor Rockstars

A server-side (and client-side) generated HTML Website generated using just ServiceStack's built-in Razor and Markdown Razor HTML support. It shows how existing ServiceStack services can be enhanced with Razor views enabling the same Service to power both a web site and rich native Desktop and Mobile clients.

Northwind.Data

Another rich server-side website further illustrating the ability of being able to build both a feature-rich website as well as REST and typed message-based APIs re-using the same ServiceStack services, serving both browsers and native Desktop and Mobile clients. Other than providing a rich browsing experience it shows how to provide a rich OData-like experience using LLBLGen.

Matt Cowan provides a good tutorial of how he built Nortwind.Data on his blog and provides a Great Followup showing how to add Theming to ServiceStack Razor Views.

Real-time Order fulfillments

StarBucks-like real-time ordering fulfillment Single Page App built with ServiceStack, MVC, AngularJS, SignalR, Sqlite and Redis. Supports different user roles where any User can create an order which gets placed in a Queue and can be fulfilled by an authenticated 'Fulfiller'.

Social Bootstrap API

A Backbone.js-based Single Page App built with ServiceStack + ASP.NET MVC showing how to enable all different Authentication Providers in a single App, be able to connect to Social APIs and the different ways of how to integrate ServiceStack + MVC.

ServiceStack.UseCases

We've changed the way we're creating demo applications, instead of complete stand-alone example apps we're developing single-purpose applications showcasing a single use-case.

  • Custom Authentication and Integration with ASP.NET
  • Custom Authentication and Integration with ASP.NET MVC
  • Different ways to say Hello, with built-in Content-Types, text, html and generating a dynamic image
  • Image Resizer - A Single Page App in 1 C# and 1 HTML page allowing uploads of any image via Form Upload or Url, resizing and cropping each image in the different pre-set resolution sizes for all iOS devices
  • Reusability - showcasing how you can re-use the same services inside MQ hosts to provide instant response times and transparent parallel execution
  • Poco Power - Showing how you can re-use the same POCOs in all ServiceStack client libraries. From maintaing complex types in Web.config to creating DB tables with OrmLite to calling 3rd Party twitter and GitHub REST APIs and storing and retrieving them in RDBMS and Redis
  • Use node.js as a front-end proxy to a backend ServiceStack instance on Windows and OSX/Linux
  • Swagger Hello World - Simple service with Swagger integration and features enabled
  • WebApi Products Example - Showcase the differences rewriting WebApi products into a ServiceStack service

ServiceStack.Examples

Where all ServiceStack example projects were kept containing simple, stand-alone, single-purpose focused single page apps.

  • Hello World, Setting up ServiceStack and creating a Hello World Service
  • Backbone TODOs - The simplest REST/CRUD app built with ServiceStack
  • ServiceStack Docs is an example of a Content Heavy Ajax site using built just using Markdown Razor
  • A mini StackOverflow Single Page App built using just ServiceStack + Redis
  • GitHub REST Files - Showing how to build an WebDAV-like online file system manager
  • REST Intro - showing how to structure and physically layout a simple REST app
  • Movie REST - visualizing the different REST operations as they happen
  • Northwind database viewer, showing how to easily expose read and cached view services of an internal dataset with ServiceStack + OrmLite

Starter Templates

Different working starting templates for popular configurations of ServiceStack:

  • At custom path, like /api
  • At / root path
  • A stand-alone HttpListener Console AppHost
  • A Windows Service AppHost

ServiceStack: RESTful Resource Versioning

Try to evolve (not re-implement) existing services

For versioning, you are going to be in for a world of hurt if you try to maintain different static types for different version endpoints. We initially started down this route but as soon as you start to support your first version the development effort to maintain multiple versions of the same service explodes as you will need to either maintain manual mapping of different types which easily leaks out into having to maintain multiple parallel implementations, each coupled to a different versions type - a massive violation of DRY. This is less of an issue for dynamic languages where the same models can easily be re-used by different versions.

Take advantage of built-in versioning in serializers

My recommendation is not to explicitly version but take advantage of the versioning capabilities inside the serialization formats.

E.g: you generally don't need to worry about versioning with JSON clients as the versioning capabilities of the JSON and JSV Serializers are much more resilient.

Enhance your existing services defensively

With XML and DataContract's you can freely add and remove fields without making a breaking change. If you add IExtensibleDataObject to your response DTO's you also have a potential to access data that's not defined on the DTO. My approach to versioning is to program defensively so not to introduce a breaking change, you can verify this is the case with Integration tests using old DTOs. Here are some tips I follow:

  • Never change the type of an existing property - If you need it to be a different type add another property and use the old/existing one to determine the version
  • Program defensively realize what properties don't exist with older clients so don't make them mandatory.
  • Keep a single global namespace (only relevant for XML/SOAP endpoints)

I do this by using the [assembly] attribute in the AssemblyInfo.cs of each of your DTO projects:

[assembly: ContractNamespace("http://schemas.servicestack.net/types", 
ClrNamespace = "MyServiceModel.DtoTypes")]

The assembly attribute saves you from manually specifying explicit namespaces on each DTO, i.e:

namespace MyServiceModel.DtoTypes {
[DataContract(Namespace="http://schemas.servicestack.net/types")]
public class Foo { .. }
}

If you want to use a different XML namespace than the default above you need to register it with:

SetConfig(new EndpointHostConfig {
WsdlServiceNamespace = "http://schemas.my.org/types"
});

Embedding Versioning in DTOs

Most of the time, if you program defensively and evolve your services gracefully you wont need to know exactly what version a specific client is using as you can infer it from the data that is populated. But in the rare cases your services needs to tweak the behavior based on the specific version of the client, you can embed version information in your DTOs.

With the first release of your DTOs you publish, you can happily create them without any thought of versioning.

class Foo {
string Name;
}

But maybe for some reason the Form/UI was changed and you no longer wanted the Client to use the ambiguous Name variable and you also wanted to track the specific version the client was using:

class Foo {
Foo() {
Version = 1;
}
int Version;
string Name;
string DisplayName;
int Age;
}

Later it was discussed in a Team meeting, DisplayName wasn't good enough and you should split them out into different fields:

class Foo {
Foo() {
Version = 2;
}
int Version;
string Name;
string DisplayName;
string FirstName;
string LastName;
DateTime? DateOfBirth;
}

So the current state is that you have 3 different client versions out, with existing calls that look like:

v1 Release:

client.Post(new Foo { Name = "Foo Bar" });

v2 Release:

client.Post(new Foo { Name="Bar", DisplayName="Foo Bar", Age=18 });

v3 Release:

client.Post(new Foo { FirstName = "Foo", LastName = "Bar", 
DateOfBirth = new DateTime(1994, 01, 01) });

You can continue to handle these different versions in the same implementation (which will be using the latest v3 version of the DTOs) e.g:

class FooService : Service {

public object Post(Foo request) {
//v1:
request.Version == 0
request.Name == "Foo"
request.DisplayName == null
request.Age = 0
request.DateOfBirth = null

//v2:
request.Version == 2
request.Name == null
request.DisplayName == "Foo Bar"
request.Age = 18
request.DateOfBirth = null

//v3:
request.Version == 3
request.Name == null
request.DisplayName == null
request.FirstName == "Foo"
request.LastName == "Bar"
request.Age = 0
request.DateOfBirth = new DateTime(1994, 01, 01)
}
}

ServiceStack Performance

Your Request DTO's should implement either IReturn<T> or IReturnVoid otherwise if you're sending just an object you will call the deprecated Post() method:

/// <summary>
/// APIs returning HttpWebResponse must be explicitly Disposed, e.g using (var res = client.Post(url)) { ... }
/// </summary>
[Obsolete("Use: using (client.Post<HttpWebResponse>(requestDto) { }")]
public virtual HttpWebResponse Post(object requestDto)
{
return Send<HttpWebResponse>(HttpMethods.Post, ResolveTypedUrl(HttpMethods.Post, requestDto), requestDto);
}

Which because ServiceStack doesn't know how you want the Response deserialized it will return the open HttpWebResponse so you can inspect the Response yourself (as you're doing in your example). But this needs to be explicitly disposed as .NET's HttpWebRequest only allows a couple of concurrent requests open per domain which will cause your App to hang/timeout as it's waiting for Requests to be disposed to stay within the concurrent limit.

The preferred solution is to always annotate Request DTO's that you send with ServiceStack clients with a IReturn or a IReturn<T> interface marker, if it has none or you want to ignore the Response implement IReturnVoid otherwise implement IReturn<ResponseDtoType>:

class LoginRequest : IReturnVoid {}

Which instead calls the non-deprecated Post() method which disposes of the HttpWebResponse.

Otherwise if you want to send plain object DTO's you need to dispose of the HttpWebResponse after usage, e.g:

using (var response = client.Post<HttpWebResponse>(new LoginRequest(accessKey, secretKey)))
{
var authorization = response.Headers.GetValues("Authorization")[0];
}

API's which implicitly return HttpWebResponse were deprecated to avoid hard to identify issues like this, instead we recommend using the explicit API above which declares the HttpWebResponse return type at the call-site so it's easier to identify it needs to be disposed.

Also note the ServiceStack Service Clients are opinionated for calling ServiceStack Services, for calling other Services we recommend using HTTP Utils instead.

What is the recommended way to do partial updates with PATCH in ServiceStack?

Declare any scalar values in your DTO as nullable. This will allow you to determine which fields were actually sent in the request:

public class MyClass {
public int? a { get; set; }
public int? b { get; set; }
public int? c { get; set; }
// etc.
// object-type properties are already nullable of course
public string MyString { get; set; }
}

Now if a client sends a partial request, like so:

{ "a": 1, "b": 0 }

You'll be able to determine which properties were actually sent when inspecting your DTO:

myClass.a == 1
myClass.b == 0
myClass.c == null
myClass.MyString == null
etc.

Set up a PATCH route for your DTO and implement a Patch method in your service:

public object Patch(MyClass request)
{
var existing = GetMyClassObjectFromDatabase();
existing.PopulateWithNonDefaultValues(request);
SaveToDatabase(existing);
...
}

PopulateWithNonDefaultValues is key here. It will copy values from your request object onto the database entity, but will only copy properties that are not the default values. Thus, if a value is null, it won't copy it, because the client didn't send a value for it. Notice that it will copy an integer value of zero though, because we made it a nullable int, and the default value for a nullable int is considered by this method to be null, not zero. Declaring your DTO properties as nullable shouldn't cause much of a hassle in the rest of your code.

Note that this approach works easily with JSON. If you need to support XML requests/responses, you may need need to do some additional work with DataContract/DataMember attributes to insure that nulls are handled correctly.

When to use DTO's and Models for ServiceStack?

You would use distinct DTO's for Data Models that make poor substitutes for serializable DTO's, e.g:

Have cyclical dependencies or overuse of Inheritance and interfaces

This is less of an issue when using code-first ORM's like OrmLite which as they encourage use of clean POCO's already make good candidates to be re-used as DTO's.

Ideally DTO's should be self-describing and non-hierarchical (i.e. flat) and not rely on serializer-specific features, inhibiting re-usability and reducing interoperability with different formats and serializers.

Doesn't match the shape of the Contract that you want to expose

Your data models might make use of internal codes (e.g. int values) which doesn't make sense to external users outside your database, in which case you may want to project them into self-describing DTO's which exposes more user-friendly labels.

You can use Auto Mapping to reduce the effort whenever you need to re-project between models.



Related Topics



Leave a reply



Submit