Dart Client: Client mapping issue in release build

Hi,
We have an issue with the dart client when accessing data from the api.
On our Endpoint we return a List to the client.
Now as stated in your documentation we needed to add List to a UnknownTypes Class on the api, so that this type is accessible for mapping in the dart client.

This solution works now as long as we are in a debug build. When we run flutter build with the --release parameter we get the error on the dart client with the message:
Unknown Type '_GrowableList<FooDto>', see: https://docs.servicestack.net/dart-add-servicestack-reference#generating-unknown-types

I now did some research on why this could be happening and found following sources:
https://www.gitmemory.com/issue/flutter/flutter/60603/651821088
https://github.com/dart-lang/language/issues/1056

They talk about that the property runtimeType in dart is not returning the same if you have a List in release or debug build.

I found now in your code that the mapping is also using this property so this seems to be the source of the issue.
https://github.com/ServiceStack/servicestack-dart/blob/master/lib/client.dart
Row 490 & 503

Could you please fix this issue, since it prevents the api from working on the target devices.

What’s the best way to repro the issue?

The Endpoint is:
class GetFoo : OrderedRequest, IReturn<List>

On Dart side:
await JsonServiceClient().get(GetFoo());

Then run the flutter app with debugger -> Api Call should work
Then build the app in release and install it on the device or simulator -> Api call fails with mentioned error

Please provide the full C# DTO (inc. References, e.g. base & Response Types).

GetAttachments.cs

[Route("/cases/{Id}/attachments", "GET")]
public class GetAttachments : OrderedRequest, IReturn<List<AttachmentDto>>
{
    public string Id { get; set; }

    [ApiMember(Description = "Filter attachments by type")]
    public AttachmentType? Type { get; set; }
}

AttachmentDto.cs

    public class AttachmentDto
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public AttachmentType Type { get; set; }
        public DateTime CreatedAt { get; set; }

        public long Size { get; set; }
    }

AttachmentType.cs

public enum AttachmentType
    {
        Picture,
        Document,
        Other,
        Uncategorized
    }

Is OrderedRequest just a normal POCO? I’ll see if I can repro it, in meantime can you check if you could work around the issue by returning a Response DTO, e.g. GetAttachmentsResponse?

OrderedRequest

public abstract class OrderedRequest
{
    [ApiMember(AllowMultiple = false, DataType = "string", Description = "Comma- or semicolon separated list of fields to sort by. To change sort order add a '-' in front of the field", IsRequired = false, Name = "OrderBy", ParameterType = "query", Verb = "GET")]
    public string OrderBy { get; set; }
}

Wrapping the List in a Response DTO works.
But to implement that we need to change other applications which also use the same api.

So a fix would be better. I also saw that endpoints which are paged are also not a problem.
The issue seems just to be when list is the top level response type.

I’ll look into it, but it’s not a bug in the client library which would instead need to embed a workaround to detect the runtime type of the implementation type for a List on a specific Dart platform, which I’m not a fan of as it’s very fragile & can break in future if the internal implementation Type changes.

ok thx for looking into it.
I hope you can work out a solution in the client library.
We will use your proposed solution by wrapping the list for the moment
but it’s no ideal to have a breaking api change just due to one client library.

Thank you for your help!

I’m not able to repro this which “runs” find in an emulator but from the description it sounds like you can work around this by registering a custom factory for the internal list type, e.g:

JsonConverters.TypeFactories['_GrowableList<FooDto>'] = () => List<FooDto>();

Can you confirm if this works?

FYI I’ve added a workaround that adds additional typeInfo entries for all registered generic types based on their instance runtimeType.toString() which hopefully resolves the issue.

Now available on pub.dev in the latest:

dependencies:
  servicestack: ^1.0.15

I put together a stand alone project (vs and flutter) that demonstrate several problems including the one from OP.

Lib versions: SS 5.9 and Flutter SS Dart 1.0.15

In the flutter app:

  • Test 1 calls a service that returns List<> and it works in the emulator but fails when installed on android. In the release app the flutter code will return a list of one when it fails (which is what happens on the device but not in the emulator).
  • Test 2 calls a service that returns QueryResponse<> and it neither works in the emulator nor the app in release mode. What I noticed here is the queryresponse’s properties are all null so it doesn’t deserialize correctly.

When adding some logging the requests are returning data correctly.

The sample project including both .net and flutter (TestFlutter you should just be able to run it) is located here.

Apk’s are available here if you want to install them but always safer to build them yourself.

I should point out if you need help testing this let me know, happy to help.

Ok the primary issue was that you’re .NET Framework project uses PascalCase whilst the internal servicestack Dart library assumed camelCase, this should be resolved from the latest release.

Can you try again with the latest version on:

dependencies:
  servicestack: ^1.0.16