Mark Seemann
Mark Seemann

Reputation: 233150

Combine URL data with HTTP POST request body in ServiceStack

I'd like to be able to POST data like this to a REST API:

POST /foo/b HTTP/1.1
Accept: application/json
Content-Type: application/json

{ "Qux": 42, "Corge": "c" }

The URL segment after foo (i.e. b) also contains data that I need to capture in a server-side variable. I've tried to implement this feature in ServiceStack (see code below), but the response body is null.

Here's first the request type:

[Route("/foo/{Bar}", "POST")]
public class PostFooRequest : IReturn<PostFooResponse>
{
    public string Bar { get; set; }

    [ApiMember(ParameterType = "body")]
    public Foo Body { get; set; }
}

As you can see, Bar is a URL variable. The Foo class is defined like this:

public class Foo
{
    public int Qux { get; set; }
    public string Corge { get; set; }
}

Furthermore, the response looks like this:

public class PostFooResponse
{
    public string Bar { get; set; }
    public Foo Foo { get; set; }
}

Finally, the service itself is defined like this:

public class ReproService : Service
{
    public object Post(PostFooRequest request)
    {
        return new PostFooResponse { Bar = request.Bar, Foo = request.Body };
    }
}

Notice that this method simply echoes the values of the request in the response.

When I execute the above request, I only get the Bar value back:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8

{"bar":"b"}

Setting a breakpoint in the Post method reveals that request.Body is null.

How do I write the code so that the API has the desired contract?

FWIW, I'm aware of this question, but the answer only explains what the problem is; not how to solve it.

Upvotes: 2

Views: 490

Answers (1)

Mark Verkiel
Mark Verkiel

Reputation: 1239

If you would translate your current request to the following DTO the serializer should be able to fill the properties:

[Route("/foo/{Bar}", "POST")]
public class PostFooRequest : IReturn<PostFooResponse>
{
    public string Bar { get; set; }

    public int Qux { get; set; }
    public string Corge { get; set; }
}

The serializer has no way to know how to deserialize the object you're sending.

Looking at your DTO and the request I would expect a different request.

POST /foo/b HTTP/1.1
Accept: application/json
Content-Type: application/json

{
    "Foo": {  "Qux": 42, "Corge": "c" }
}

Other way of retrieving the FormData would be using the following property in your Servicestack service Request.FormData. Make sure you're not calling the DTO but capital Request.

Upvotes: 2

Related Questions