Jesse Webb
Jesse Webb

Reputation: 45243

How do I map multiple Request DTOs to a single Route

I have been experimenting with the ServiceStack framework to develop a simple REST API. I am having troubles trying to define the Routes properly to handle the different URLs I desire.

I have a simple DomainModel class:

public class Student
{
    public int Id { get; set; } // unique
    public string Email { get; set; } // not unique

    // some other properties and business logic
}

I would like to create a REST service which responds to HTTP requests to the following URLs:

I have tried using the following Request DTOs to accomplish this:

[Route("/students", "GET")]
public class GetAllStudents : IReturn<StudentList>
{
}

[Route("/students", "GET")] // I want this to be for /students?Id=
[Route("/students/{Id}", "GET")]
public class GetStudentById : IReturn<Student>
{
    public int Id { get; set; }
}

[Route("/students", "GET")] // I want this to be for /students?Email=
public class GetStudentsByEmail : IReturn<StudentList>
{
    public string Email { get; set; }
}

As you can see, I am only trying to use two different Response DTOs:

public class StudentList : List<Student>
{
}

public class Student
{
    public int Id { get; set; }
    public String Email { get; set; }
}

Note: This Reponse DTO Student class is separate than my DomainModel class; they are in different namespaces.

Unfortunately, when I try to use these routes, every request to /students?<anything> ends up returning all students. The only Route that does work is if I make a GET request to /students/123, then I get back Student with Id 123. I assume this isn't working because I am re-using the "/students" Route definition for multiple Request DTOs.

I have been reading through the ServiceStack wiki and examples but I can not figure out how to accomplish what I am attempting. The most detailed documentation I can find about advanced routing is the "Smart Routing" section of the "New API" page but it doesn't really address this situation either.

How can I re-use the same Route definition for mulitple Request DTOs?

Upvotes: 3

Views: 1377

Answers (1)

mythz
mythz

Reputation: 143319

Having ByXXX suffixes on your Request DTOs is a code-smell in ServiceStack who wants to encourage the design of message-based coarse-grained interfaces. Please see this earlier answer on How to design a Message-Based API with ServiceStack and why you should group services by response types and call semantics

In this case you have a service doing a Get on a Unique Id returning a single Student and you also wish to have a Search on Email which returns multiple Students. So in this case I would have the following services:

[Route("/students/{Id}")]
public GetStudent : IReturn<Student>
{
    public int Id { get; set; }
}

Which would handle just /students/123.

[Route("/students")]
public FindStudents : IReturn<List<Student>>
{
    public int? Id { get; set; }
    public string Email { get; set; }
}

Which can be used to handle:

Although I personally wouldn't include an Id here since it's a Get instead of a Filter.

Upvotes: 5

Related Questions