1
votes

I am attempting to get ServiceStack to return a list of objects to a C# client, but I keep getting this exception:

"... System.Runtime.Serialization.SerializationException: Type definitions should start with a '{' ...."

The model I am trying to return:

public class ServiceCallModel
{

    public ServiceCallModel()
    {
        call_uid = 0;
    }

    public ServiceCallModel(int callUid)
    {
        this.call_uid = callUid;
    }

    public int call_uid { get; set; }
    public int store_uid { get; set; }

    ...... <many more properties> ......

    public bool cap_expense { get; set; }
    public bool is_new { get; set; }
    // An array of properties to exclude from property building 
    public string[] excludedProperties = { "" };
}

The response:

public class ServiceCallResponse
{
    public List<ServiceCallModel> Result { get; set; }
    public ResponseStatus ResponseStatus { get; set; } //Where Exceptions get auto-serialized
}

And the service:

public class ServiceCallsService : Service 
{
    // An instance of model factory
    ModelFactory MyModelFactory = new ModelFactory(); 

    public object Any(ServiceCallModel request)
    {
        if (request.call_uid != 0)
        {
            return MyModelFactory.GetServiceCalls(request.call_uid); 
        } else { 
            return MyModelFactory.GetServiceCalls() ; 
        }
    }
}

The client accesses the service with:

        JsonServiceClient client = new ServiceStack.ServiceClient.Web.JsonServiceClient("http://172.16.0.15/");
        client.SetCredentials("user", "1234");
        client.AlwaysSendBasicAuthHeader = true;
        ServiceCallResponse response = client.Get<ServiceCallResponse>("/sc");

The "model factory" class is a DB access class which returns a list. Everything seems to work just fine when I access the service through a web browser. The JSON returned from the service starts:

"[{"call_uid":70...."

And ends with:

"....false,"is_new":true}]"

My question is, what here might be causing serialization/deserialization to fail?

Solution

Thanks to the answer from mythz, I was able to figure out what I was doing wrong. My misunderstanding was in exactly how many DTO types there are and exactly what they do. In my mind I had them sort of merged together in some incorrect way. So now as I understand it:

Object to return (In my case, called "ServiceCallModel": The actual class you wish the client to have once ServiceStack has done its job. In my case, a ServiceCallModel is a key class in my program which many other classes consume and create.

Request DTO: This is what the client sends to the server and contains anything related to making a request. Variables, etc.

Response DTO: The response that the server sends back to the requesting client. This contains a single data object (ServiceCallModel), or in my case... a list of ServiceCallModel.

Further, exactly as Mythz said, I now understand the reason for adding "IReturn" to the request DTO is so the client will know precisely what the server will send back to it. In my case I am using the list of ServiceCallModel as the data source for a ListView in Android. So its nice to be able to tell a ListViewAdapter that "response.Result" is in fact already a useful list.

Thanks Mythz for your help.

1
public ResponseStatus ResponseStatus try renaming the object to something like MyResponseStatusPaddyd

1 Answers

2
votes

This error:

Type definitions should start with a '{' 

Happens when the shape of the JSON doesn't match what it's expecting, which for this example:

ServiceCallResponse response = client.Get<ServiceCallResponse>("/sc");

The client is expecting the Service to return a ServiceCallResponse, but it's not clear from the info provided that this is happening - though the error is suggesting it's not.

Add Type Safety

Although it doesn't change the behavior, if you specify types in your services you can assert that it returns the expected type, e.g Change object to ServiceCallResponse, e.g:

public ServiceCallResponse Any(ServiceCallModel request)
{
    ...
}

To save clients guessing what a service returns, you can just specify it on the Request DTO with:

public class ServiceCallModel : IReturn<ServiceCallResponse>
{
    ...
}

This lets your clients have a more succinct and typed API, e.g:

ServiceCallResponse response = client.Get(new ServiceCallModel());

instead of:

ServiceCallResponse response = client.Get<ServiceCallResponse>("/sc");

See the New API and C# Clients docs for more info.