Bolero icon indicating copy to clipboard operation
Bolero copied to clipboard

Elmish subscription wrapper around a SignalR-connection

Open brikken opened this issue 4 years ago • 11 comments

Quoting Elmish

Sometimes we have a source of events that doesn't depend on the current state of the model, like a timer.

A push message through a SignalR-connection could be considered such an external event.

Is this something you think belongs in the core of Bolero?

brikken avatar Jan 14 '20 17:01 brikken

@brikken that's Cmd.ofSub, it works the same way as in Elmish, nothing special in them. Another thing you can do is , you can get dispatcher from Program and use it to push messages.

OnurGumus avatar Jan 14 '20 18:01 OnurGumus

I agree, I don't think it belongs in the core of Bolero but we could probably make a nice little helper library for it.

Tarmil avatar Jan 14 '20 18:01 Tarmil

A brief status to let you know where I am on this.

After hours of frustation I realize that the SignalR .NET Core client does not work in Blazor WebAssembly, and fails silently. This puzzles me, since they write

The Blazor WebAssembly app can interact with the server over the network using web API calls or SignalR.

Instead, this is needed, but in that case it works beautifully when injecting it into the App component.

Next step is to add type checking to the communication, preferably in a style as close as possible to the Bolero.Remoting

brikken avatar Jan 22 '20 21:01 brikken

There are two SignalR adapters for Blazor: Blazor.Extensions.SignalR, which is the one you linked, and BlazorSignalR. Currently, they're both not working properly because the latest Blazor changed how to include external js scripts (and in fact, removed the ability to do so automatically 😕). But BlazorSignalR has the advantage of having a long poll-based implementation that does not rely on external js, so that is currently working. I just switched the implementation of the HTML template hot reload to BlazorSignalR because of this: https://github.com/fsbolero/Templating.HotReload/commit/25345b3a7b02959078c903de18c5464899891128

Tarmil avatar Jan 23 '20 10:01 Tarmil

@brikken https://github.com/BlazorExtensions/SignalR/issues/66 might be helpful

OnurGumus avatar Jan 23 '20 10:01 OnurGumus

Thank you, @OnurGumus, I made it work using the resources you linked to. It's currently a manual job to include the compiled js, but that'll do for now. It appears the .NET client will be coming to WASM eventually.

I've currently stumbled upon another problem where the format of the SignalR JSON reply is different between a Hub and Hub<T>, causing confusion in Blazor.Extensions.SignalR. I may have to work around this, or at least encapsulate it, when wrapping the whole connection in a typed setup.

brikken avatar Jan 26 '20 13:01 brikken

Another issue has shown up. The JSON serializer doesn't serialize discriminated unions properly.

    type HubRecord = { fieldA: string; fieldB: int list; }
    type HubDu = | CaseA | CaseB of string
    type HubClass() = member val Number : int = 10
    
    type ITypedTestHub =
        abstract ReceiveData : (int * string list * HubRecord * HubDu * HubClass) -> System.Threading.Tasks.Task
    
    type TypedTestHub() =
        inherit Hub<ITypedTestHub>()
        let data = (10, ["Hello"; "World!"], { fieldA = "Bar"; fieldB = [1;2;3]}, CaseB "Foo", HubClass())
        override this.OnConnectedAsync() = this.Clients.All.ReceiveData(data)

is serialized to

{"item1":10,"item2":["Hello","World!"],"item3":{"fieldA":"Bar","fieldB":[1,2,3]},"item4":{"tag":1,"isCaseA":false,"isCaseB":true},"item5":{"number":10}}

Notice that isCaseB = true, but the string value Foo is not included anywhere in the serialization.

@Tarmil, I can see that Bolero.Remoting serializes discriminated unions properly. Could that method be re-used here? Edit: Found it!

brikken avatar Jan 26 '20 20:01 brikken

@brikken looks like SignalR client is now available on WASM? https://devblogs.microsoft.com/aspnet/blazor-webassembly-3-2-0-preview-1-release-now-available/

I have not tried myself, so I'm keen to hear your findings.

wilsoncg avatar Jan 29 '20 11:01 wilsoncg

Looking exciting, that should iron out some of the kinks. I'll keep you posted on my progress here.

I'll be going on vacation soon, though, so it may be quiet for a couple of weeks.

brikken avatar Jan 29 '20 17:01 brikken

Bolero doesn't compile with Blazor.Build 3.2.0-preview1.20073.1 so no luck so far

brikken avatar Jan 31 '20 23:01 brikken

I am using the standard SignalR library in a Bolero application (.NET 5) and was able to get it hooked into a Elmish subscription. I am fairly new to F# but could help create this helper library or at least maybe a template to demonstrate how to do it. Thanks to this comment I got it working with JSON. It also works with MessagePack just fine as well.

sdehm avatar Sep 13 '21 20:09 sdehm