Emon
Emon

Reputation: 841

Handling multiple get operations

I am fairly new to ServiceStack and I am trying to figure out the best practices around handling multiple get operations on the same request. Below is my request object:

[Route("/Entity", Verbs = "GET", Notes = "Returns all the entities.")]
[Route("/Entity/{Id}", Verbs = "GET", Notes = "Returns a specific entity.")]
[Route("/Entity/{Id}/Child", Verbs = "GET", Notes = "Returns children of a specific entity.")]    
public class EntityRequest {
    public int Id { get; set; }
    public int ChildId { get; set; }
}

And below is my service:

public object Get(EntityRequest request) {
        if (request.Id > 0) {
            //returns a given entity
            return _applicationService.getEntities(request.Id);
        }

        //How do I handle this? Check for the word "/Child" in the URL?
        //returns children for a given entity
        //return _applicationService.getChildren(request.Id);

        //returns all the entities
        return _applicationService.getEntities();
    }
}

As you can see I am handling the first two routes "/Entity" and "/Entity/{Id}" from the service side. How can I best handle the "/Entity/{Id}/Child" route? At the current state, the third URL will return all the entities. Any help will be appreciated?

Thanks!

Upvotes: 3

Views: 98

Answers (1)

mythz
mythz

Reputation: 143399

Have a look at these existing answers below which go through the recommended way to design Services with ServiceStack:

The recommendation is to have a different Service if the response is different. Your Services should also be self-descriptive, rather than relying on the documentations in the Notes to describe each Service (which very few people read), so I would redesign your Services into something like:

[Route("/entities")]
public class GetAllEntities : IReturn<GetAllEntitiesResponse> {}

public class GetAllEntitiesResponse
{
    public List<Entity> Results { get; set; }
}

If you would also like your Service to be able to provide the ability to query entities have a look at AutoQuery which lets you create a fully-queryable RDBMS-backed Service with just the Request DTO below:

[Route("/entities/search")]
public class QueryEntities : QueryBase<Entity> {}

The remaining Services are similar a separate Request DTO for each different type of Service where the Request DTO would contain all the properties required for calling that Service, e.g:

[Route("/entities/{Id}")]
public class GetEntity : IReturn<GetEntityResponse>
{
    public int Id { get; set; }
}

public class GetEntityResponse
{
    public Entity Result { get; set; }
}

Likewise for Child Entities Service:

[Route("/entities/{Id}/children")]
public class GetEntityChildren : IReturn<GetEntityChildrenResponse>
{
    public int Id { get; set; }
}

public class GetEntityChildrenResponse
{
    public List<EntityChild> Results { get; set; }
}

Designing your Service this way makes it explicit what each Service does, the parameters each Service expect and what it returns. It's also reflected when calling the above Services with ServiceStack's Typed Service Clients, e.g:

var response = client.Get(new GetAllEntities());
var response = client.Get(new GetEntity { Id = 1 });
var response = client.Get(new GetEntityChildren { Id = 1 });

My personal preference is to use an explicit Response DTO for each Service as it future proofs the Service and lets you later evolve the Service to return additional results later without breaking existing Service Clients, but if you prefer you can instead return the results directly without an explicit Response DTO wrapper, e.g:

[Route("/entities")]
public class GetAllEntities : IReturn<List<Entity>> {}

[Route("/entities/{Id}")]
public class GetEntity : IReturn<Entity>
{
    public int Id { get; set; }
}

[Route("/entities/{Id}/children")]
public class GetEntityChildren : IReturn<List<EntityChild>>
{
    public int Id { get; set; }
}

Upvotes: 4

Related Questions