One service with different request types?

1,009 views
Skip to first unread message

mj1856

unread,
Jan 25, 2012, 4:23:50 PM1/25/12
to ServiceStack .NET Open Source REST Web Services Framework
Sorry if this has been answered somewhere, but I searched to no avail.

Is it possible to have a single service with multiple different
request types?

For example, I am creating an EmployeeService. For GET requests, I
might pass in an EmployeeRequestDto that just has the EmployeeID. It
would return an EmployeeDto of the actuall employee record. A POST
request would accept an EmployeeDto and do an update or insert.

If I inherit from RestServiceBase<EmployeeDto>, I can override OnPost
for the update method, but when overriding OnGet, it would also expect
a full EmployeeDto object, rather than an EmployeeRequestDto.

I can create two separate services, one for retrieval and one for
updates, but this seems counterproductive.

Is there a better way to do this?

Demis Bellot

unread,
Jan 25, 2012, 4:52:14 PM1/25/12
to servic...@googlegroups.com
To start off, I dislike suffixing the name 'Request' to the Request DTO and suffixing 'Dto' to any of the DTOs.

The web service interface (i..e service contract) is the most important interface your system has and as such should be a first class concept.
i.e. for all intents and purposes the Request DTO *is* your web service so it should use a first class Resource name like 'Employees' i.e. hiding impl specifics like it's a Request DTO.

And the convention name for the Response DTO is RequestDto + 'Response' so in this case 'EmployeesResponse', this allows the ServiceStack to predict the return type and be able to auto-serialize exceptions into the ResponseStatus property for you.
It also allows service clients to predict the stong-typed response DTO for each web service without needing to look up documentation for each one. Basically sticking to this convention is generally a productivity win.

With that said, each RestServiceBase contains the implementation for 1 Request DTO, i.e. your REST Service.
So if you want to use different DTOs you need to create different services.

If you go this route you can make both services respond to the same /employees route, using different verbs (i.e. masking there are multiple service impls for the same route).
Here is an example using Employees:

[RestService("/employees", "GET")]
class Employees {}
class EmployeesResponse {}

class EmployeesService : RestServiceBase<Employees> {
   ...
   OnGet(Employees request) {
      return new EmployeesResponse { Results = Repo.GetAllEmloyees() };
   }
}

[RestService("/employees", "POST")]
class Employee {}
class EmployeeResponse {}

class EmployeesService : RestServiceBase<Employees> {
   ...
   OnPost(Employee request) {
      return new EmployeesResponse { Result = Repo.StoreEmployee(request.TransalteTo<EmployeeDataModel>()) };
   }
}

With this setup GET /employees go to the first service, whilst POST /employees go to the second, etc.

Now the Request DTO just contains strong-typed access to all the data your REST web service accepts, so you the other approach is to stick with one service but to merge all the fields that each of your VERBs need into the one Request DTO.
So effectively each REST Verb handler only uses a subset of the fields on your Request DTO where for this example all your full Employee fields gets merged with the fields required for processing GET requests.

Cheers,

mj1856

unread,
Jan 25, 2012, 5:52:35 PM1/25/12
to ServiceStack .NET Open Source REST Web Services Framework
Thanks. I'll give that a try. It sounds right, it's just different
than what I'm used to.

Coming from a WCF services background, I'm used to thinking of the
service (not the DTO) as the first class citizen. I'll have to get
used to this new way of thinking.

In my current project (following DDD), an Employee would be an entity
in the domain layer, which gets persisted back to the database through
a repository. So I have a DTO layer that contains things like
EmployeeDto. The DTO layer is set up as with linked projects, dual-
compiled for regular .Net and for Silverlight. So when I call the
EmployeeService with something like GetEmployeeByID(int ID), then I
would return an EmployeeDto so it can be serialized, sent down the
wire, and deserialized to the same DTO in the Silverlight client. The
EmployeeDto naming convention was to separate them from the Employee
entities. We use AutoMapper to bind them.

So if I'm understanding correctly, I'll want two DTOs now, one for
requests and one for responses. I'm a bit fuzzy on why the response
would be called EmployeeResponse. Let's consider the use case of
searching for an employee by name and active/inactive status. In the
past, I'd write a web service that would be something like
GetEmployee(string name, bool isActive). The name could be a partial
search string. I might have other ways of searching also, which is
why I included the isActive flag. Are you saying that I should just
have Employee and EmployeeResponse? It seems more natural to me that
I might have something like:

public class EmployeeRequest
{
public int? Id {get; set;}
public string Name {get; set;}
public bool? IsActive {get; set;}
... other possible search parameters ...
}

public class Employee
{
public int Id {get; set;}
public string Name {get; set;}
public string EmpNumber {get; set;}
public bool IsActive {get; set;}
}

That way I could look at non-nullable fields on the request and return
things accordingly. For example, if an Id was specified, then I'd
return one Employee, but if Id was null, I might return
IEnumerable<Employee>.

Then I would need the second service that you mentioned (routing via
post method helps, thanks!). It would take the Employee object and
perhaps return something like

public class EmployeeResponse
{
public bool Ok {get; set;}
}

Does this sound about right? Or maybe I've still got my head around
WCF ways of thinking about services...


BTW - I heard about ServiceStack while catching up on HanselMinutes
archives. Great interview! The timing couldn't be better, since I
was just about fed up with WCF and looking for alternatives. I will
try to contribute back as I can.
> http://twitter.com/demisbellothttp://www.servicestack.net/mythz_blog- Hide quoted text -
>
> - Show quoted text -

Demis Bellot

unread,
Jan 25, 2012, 7:06:15 PM1/25/12
to servic...@googlegroups.com
Basically with ServiceStack we try to blend the best parts of the REST + SOA worlds.

With REST we try to design our services around Resources (i.e. Nouns) where we no longer have Action + Customers (e.g. GetCustomers) and we just expose the service like GET Customers.
Generally with SOA style services we have well-defined strong-typed, batchful, coarse-grained interfaces where it's not uncommon to have the same service be able to be called in a variety of different ways/permutations (as long it returns the same results).
Following good remote service patterns you would split your web service in 3 well-defined areas:

  + DTOs (i.e. Request/Response + Dtos) - to take care of the serialization/deserialization and wireformats concerns
  + ServiceInterface (i.e. RestServiceBase/ServiceBase) - your web service implementation handling
  + ServiceGateway (i.e. JsonServiceClient/Xml/etc) - encapsulate all client gateway logic using the generic service clients + dtos.

ServiceStack promotes this clean separation as DRY, idiomatically in C#, with strong-typed clean models end-to-end, using fast, resilient versionable serializers where possible (JSON/JSV).

Now when you talk about a web service you should be thinking about the Request / Response DTOs as this defines your web service contracts (i.e. what it accepts/returns).
So to look for information on how to call the 'Customers' service you would look at the 'Customers' request DTO (i.e. the service impl is an internal impl concern). 

Now it's important to have conventions so you can predict what the Response type for every service is, without looking at the documentation / code. 

var client = new JsonServiceClient(url);
var response = client.Send<CustomersResponse>(new Customers { Ids = { 1,2,3 });
Console.WriteLine(response.Results.Dump());

If you want ServiceStack to automatically serialize your C# exceptions for you (i.e. so it can find it) than your Response DTO should be called RequestDto + 'Response' and have a ResponseStatus property. 
Sticking to conventions also lets you have generic client logic, e.g. to handle validation logic generically applying validation errors to matching validation labels on form fields.

Its also a productive way to navigate your code base because if you have a Customers web service, the Request DTO is 'Customers' the Response DTO is 'CustomersResponse' and the impl is in the 'CustomersService' class.
Even though they're all decoupled, you can use VS.NET/R# to navigate to each of them with ease - because you're following convention, never needing to remember the name or what each service returns, etc. 
Conventions are a great way to reduce complexity by reducing industrial knowledge.

With that out of the way, using the example from https://gist.github.com/1386381 
A Customer Service in ServiceStack that allows you to retrieve customers with any combination of Customer Ids / UserNames / Emails, etc would look something like:

public class Customers {
   int[] Ids;
   string[] UserNames;
   string[] Emails;
}
public class CustomersResponse {
   Customer Result;
   Customer[] Results;
}

The equivalent design in WCF would be something Chatty and client specific like:

public interface IService
{
  Customer GetCustomerById(int id);
  Customer[] GetCustomerByIds(int[] id);
  Customer GetCustomerByUserName(string userName);
  Customer[] GetCustomerByUserNames(string[] userNames);
  Customer GetCustomerByEmail(string email);
  Customer[] GetCustomerByEmails(string[] emails);
}

I've explained some of the benefits of the ServiceStack way in https://gist.github.com/1386381 

You can use AutoMapper although mapping functionality exists in ServiceStack via the TranslateTo<T> and PopulateFrom<T> and related extension methods, you can see some examples at:

Let's consider the use case of searching for an employee by name and active/inactive status. 

Just as a matter of personal taste I separate my Get's which acts more like an OR where you expect to get an extra result for every Id/username/email/etc.
A search service acts like an AND where every field you provide FILTERS the results and reduces the result set returned.

So for this example I would leave the GETs by ids into a service like the Customer service above and have a new service for searching something like:

public class EmployeeSearch
{
  public string Name {get; set;}
  public bool? Active {get; set;}
}

public class EmployeeSearch
{
  public List<Employee> Results {get; set;}
}

You could expose this on a route like:

Routes.Add<EmployeeSearch>("/employees/search/{Name}");

letting you call it like:

/employees/search/Ste?active=true

Which would return all active employees with names starting with 'Ste*'.

For an employees Get service it could be something like:

public class EmployeesService : RestServiceBase<Employees>
{
    public IRepository Repository { get; set; } //Injected in IOC as defined in AppHost

    protected override object OnGet(Employees request)
    {
        var ids = request.Ids ?? new List<int>();
        var userNames = request.UserNames ?? new List<string>();

        var results = new List<Employee>();
        if (userIds.Count > 0)
          results.AddRange(Repository.GetEmployeesByIds(ids).ConvertAll(x => x.TranslateTo<Employee>()));
        if (userNames.Count > 0)
          results.AddRange(Repository.GetEmployeesByUserNames(userNames).ConvertAll(x => x.TranslateTo<Employee>()));

        return new EmployeesResponse { Results = results };
    }
}

Then I would need the second service that you mentioned (routing via post method helps, thanks!).   It would take the Employee object and perhaps return something like
public class EmployeeResponse {
 public bool Ok {get; set;}
}

Close but you dont need to return a flag, returning without a client exception is all the client needs to work out if its ok since C# exceptions are automatically converted to HTTP errors (which for ArgumentsExceptions are 400, AuthErrors 401, Others Exceptions get 500). 
Information about the exception is available on the client Response DTOs ResponseStatus property. You can futher customize the HTTP result by returning a HttpError(dto). 

The timing couldn't be better, since I was just about fed up with WCF and looking for alternatives.  I will try to contribute back as I can.

Sweet glad to hear it, always looking for more contributions, blog posts showing how to use ServiceStack, etc.

Cheers,

mj1856

unread,
Jan 25, 2012, 8:00:16 PM1/25/12
to ServiceStack .NET Open Source REST Web Services Framework
Thank you for the very detailed response. This makes a lot of sense
now.

Where I was getting confused is that in many things people use plural
forms of nouns "customers" where they should IMHO use singular
"customer". I was overlooking the "s" in your previous examples.

Also, I think it will work well if I think of converting verbs to noun
forms. Perhaps "Query" and "Action" are good distinguishers.

So my DTOs will look like:

public class Employee
{
public int Id {get; set;}
public string Name {get; set;}
public string EmpNumber {get; set;}
... etc ...
}

[RestService("/employees", "GET")]
public class EmployeeQuery
{
public int? Id {get; set;}
public string Name {get; set;}
... other optional search/lookup criteria ...
}

public class EmployeeQueryResponse
{
public IEnumerable<Employee> Results {get; set;}
}

[RestService("/employees", "POST,PUT,DELETE")]
public class EmployeeAction
{
public Employee Employee {get; set;}
}

public class EmployeeActionResponse
{
... not sure what should return then ...
}


Sound about right? If I don't need an ok flag, but I do need
a ...Response object, then what should be inside
EmployeeActionResponse?

-Matt


On Jan 25, 5:06 pm, Demis Bellot <demis.bel...@gmail.com> wrote:
> Basically with ServiceStack we try to blend the best parts of the REST +
> SOA worlds....
>
> read more »
> With that out of the way, using the example fromhttps://gist.github.com/1386381
> A Customer Service in ServiceStack that allows you to retrieve customers
> with any combination of Customer Ids / UserNames / Emails, etc would look
> something like:
>
> public class Customers {
>    int[] Ids;
>    string[] UserNames;
>    string[] Emails;}
>
> public class CustomersResponse {
>    Customer Result;
>    Customer[] Results;
>
> }
>
> The equivalent design in WCF would be something Chatty and client specific
> like:
>
> public interface IService
> {
>   Customer GetCustomerById(int id);
>   Customer[] GetCustomerByIds(int[] id);
>   Customer GetCustomerByUserName(string userName);
>   Customer[] GetCustomerByUserNames(string[] userNames);
>   Customer GetCustomerByEmail(string email);
>   Customer[] GetCustomerByEmails(string[] emails);
>
> }
>
> I've explained some of the benefits of the ServiceStack way inhttps://gist.github.com/1386381
> Information about the exception is available on the client Response DTOs *
> ResponseStatus* property. You can futher customize the HTTP result by
> > impl- Hide quoted text -

mj1856

unread,
Jan 25, 2012, 8:48:29 PM1/25/12
to ServiceStack .NET Open Source REST Web Services Framework
It just occured to me. When I "PUT" an EmployeeAction, I'm doing an
insert for a new Employee. So a good response might be:

public class EmployeeActionResponse
{
public int Id {get; set;}
}

The service can then return the newly generated employee id. I can
populate it for the update and delete as well, for consistancy, but
it's most valuable for the insert.

Anything else you can think I might want in the ActionResponse for
basic CRUD services?

-Matt
> > > GetEmployee(string name, bool isActive).  The name- Hide quoted text -
>
> - Show quoted text -...
>
> read more »

Demis Bellot

unread,
Jan 25, 2012, 9:07:25 PM1/25/12
to servic...@googlegroups.com
Sound about right?  If I don't need an ok flag, 

If a service just accepts and acts on an Employee, I generally like to leave it as Employee

public class Employee {
   public int Id {get; set;}
   public string Name {get; set;}
   public string EmpNumber {get; set;} 
}
public class EmployeeResponse {

 ... not sure what should return then ...
}

Note: You can use the [RestService] attribute or the fluent Routes configuration in your AppHost to define your service routes. E.g. the same Route could be defined as:

Routes.Add<Employee>("/employees", "POST PUT DELETE");

This can be nice since it allows you to leave your DTOs clean and attribute-free :)

but I do need a ...Response object, then what should be inside EmployeeActionResponse? 

Note returning an empty Response object is a good success response as the client still expects the Response DTO and it wont throw.

Cheers,

Demis Bellot

unread,
Jan 25, 2012, 9:11:25 PM1/25/12
to servic...@googlegroups.com
For a pure REST-ful response you would return a 201 Created with a url to the newly created resource.

The Movie REST demo shows an example of how to do this in ServiceStack, e.g:

return new HttpResult(newEmployee) {
  StatusCode = HttpStatusCode.Created,
  Headers = {
    { HttpHeaders.Location, this.RequestContext.AbsoluteUri.CombineWith(newMovieId) }
  }
};

Although since it requires more code, I only do this when I need to.
Returning the full newly created/updated employee in the 'Emplyee Result' property is a also a good approach.

Cheers,
Reply all
Reply to author
Forward
0 new messages