Sending a complex object to a service stack using a GET request

For a while all my ServiceStack services have been using the POST verb for incoming requests sent by clients. In this particular scenario though, I want to use the GET verb, and I want to be able to pass a fairly complex object (for example, containing arrays.)

This is my ServiceStack code:

[Route("Test")]
public class TestRequest : IReturn<TestResponse>
{
    public Criteria Criteria { get; set; }
}

public class Criteria
{
    public string Msg { get; set; }
    public string[] Keys { get; set; }
}

[DataContract]
public class TestResponse
{
    [DataMember]
    public string Text { get; set; }

    [DataMember]
    public ResponseStatus ResponseStatus { get; set; }
}

public class TestService : ServiceInterface.Service, IGet<TestRequest>, IPost<TestRequest>
{
    public object Get(TestRequest request)
    {
        return HandleRequest(request);
    }

    public object Post(TestRequest request)
    {
        return HandleRequest(request);
    }

    private object HandleRequest(TestRequest request)
    {
        if (request == null) throw new ArgumentNullException("request");

        if (request.Criteria == null)
            throw new ArgumentException("Criteria is null.");

        return new TestResponse
        {
            Text =
                String.Format(
                    "Text: {0}. Keys: {1}",
                    request.Criteria.Msg,
                    String.Join(", ", request.Criteria.Keys ?? new string[0]))
        };
    }
}

Which is consumed by an HTML application with the following jQuery code:

$(document).ready(function () {
    $.when($.ajax({
        url: '/Test',
        type: 'get',
        dataType: 'json',
        contentType: 'application/json',
        data: {
            "criteria": JSON.stringify({
                "msg": "some message",
                "keys": ["key1", "key2"]
            })
        }
    }).done(function (response) {
        console.log(response);
    }).fail(function (response) {
        console.log(response);
    }));
});

My Criteria object gets created but the Msg and Keys properties are null.

With the following POST example, the application works as intended:

$(document).ready(function () {

        $.when($.ajax({
            url: '/Test',
            type: 'post',
            dataType: 'json',
            contentType: 'application/json',
            data: JSON.stringify({
                "criteria": {
                    "msg": "some message",
                    "keys": ["key1", "key2"]
                }
            })

        }).done(function (response) {
            console.log(response);
        }).fail(function (response) {
            console.log(response);
        }));
    });

What am I misunderstanding?

Upvotes: 1

Views: 1993

Answers (2)

Sushanth --
Sushanth --

Reputation: 55750

When you use JSON.stringify with a GET request, the query string is not well-formed...

Upvotes: 0

mythz
mythz

Reputation: 143399

Note: You can't mix and match JSON strings with a JSON object (that is, typed POCO in C#).

You're trying to send a serialized JSON string which gets escaped in a JSON string, for example:

"{\"msg\":..."

On the wire into a POCO which is expecting a JSON object, for example:

{"msg":...

If the criteria was a string, for example:

public class TestRequest : IReturn<TestResponse>
{
    public string Criteria { get; set; }
}

It should work, otherwise you need to change your JSON request to send a JSON object and not a JSON object serialized + escaped into a JSON string.

Upvotes: 1

Related Questions