Zaid-Ajaj / Fable.Remoting

Type-safe communication layer (RPC-style) for F# featuring Fable and .NET Apps
https://zaid-ajaj.github.io/Fable.Remoting/
MIT License
273 stars 55 forks source link

Failure with transferring 'obj'? #121

Closed Dzoukr closed 5 years ago

Dzoukr commented 5 years ago

Hello @Zaid-Ajaj,

it's been a while. Today I found strange issue and not sure if it's bug or I do it wrong.

I have an API definition:

type API = {
    Test : unit -> Async<obj>
}

with default implemenation:

let api : API = {
    Test = fun _ -> async { return (box "TEST STRING")}
}

Transfer is ok

image

But on Fable side i got to error part of Cmd.ofAsync function:

image

Got any idea what I am doing wrong? This code is just to reproduce of course. In real world I transfer record with obj on it.

Thanks for any help 🙏

Zaid-Ajaj commented 5 years ago

Hello Roman!

At first glance, this error is expected to happen: the client cannot infer type information from the data at runtime (i.e. the type of the the boxed inner value), only metadata that is types available at compile-time.

Basically when you say: "Here is an obj" the client goes ¯\_(ツ)_/¯ "What do I do with it?".

So can you help me out a bit here:

Dzoukr commented 5 years ago

Hello!

I am trying to work Azure Search API, which is very vague about what kind of values are returned in thing called Facet.

I have basically shared type:

type RangeFacet =
    | From of obj
    | To of obj
    | FromTo of obj * obj

The obj here can be string, decimal, int32 or int64 . Actually, I don't care about value on frontend, I just need to display it (.ToString())

To achieve it, I currently created my own FacetValue union with describing all the possible values, so no problem if you close this issue. I just thought it is possible to somehow pass untyped value from backend. I am not javascript guy at all so I expected to be there something like obj in javascript. :)

Zaid-Ajaj commented 5 years ago

To achieve it, I currently created my own FacetValue union with describing all the possible values,

This is the right way to do it! Though you can simplify the the type you send to your frontend to something that only includes the formatted string if you only need the .ToString() representation

I just thought it is possible to somehow pass untyped value from backend. I am not javascript guy at all so I expected to be there something like obj in javascript. :)

It is technically possible to send obj of primitive values to the client and with some clever tricks, be able to work them there too

I can work it out by including the FullName of the boxed type into the serialized data from the backend and then inspect this FullName from the frontend as well to determine what to do during deserialization

but this "feature" has many downsides:

In conclusion, adding support for obj doesn't seem like a good idea. I will add this to the docs sometime soon, maybe a section "Supported Types" would be appropriate.

Dzoukr commented 5 years ago

Thanks @Zaid-Ajaj for great explanation and fully agree - because of one uncommon use case you should not put stability of such great library in risk.

Anyway, that's why I like talking with you - one can always learn something new. Thanks again!

Zaid-Ajaj commented 5 years ago

Thanks Roman for the kind words, really appreciate it :heart:

Keeping the features at a bare-minimum has indeed resulted in a stable library yet these bugs still creep out every now and then so thanks a lot for taking the time to report these issues!