I have a blazor server app, that calls an injected service to call a web socket in javascript to get some data. I want the web socket to return the data to a c# instance callback on the service. The c# callback works fine from the javascript method, but not from the any of the websocket callbacks (e.g. onmessge, onerror, onclose, etc.). No errors, just no data.
I have tried making the instance a global javascript and even a static value in the calling class, but still does not work. I have googled to no end and tried every suggestion, but still no luck.
Here is index page:
@page "/"
@inject BlazorJavaScriptCallback.IService1 _service1
<h1>Hello, world!</h1>
<p>And the answer back from the web service is @Message</p>
@code {
protected string Message {get; set;}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
Message = await _service1.CallWebService();
StateHasChanged();
}
}
}
The service:
using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace BlazorJavaScriptCallback
{
public interface IService1
{
Task<string> CallWebService();
}
public class Service1 : IService1
{
AutoResetEvent _stopWaitHandle = new AutoResetEvent(false);
String _message;
private IJSRuntime _jsruntime;
public Service1(IJSRuntime jsruntime)
{
_jsruntime = jsruntime;
}
public async Task<string> CallWebService()
{
_message = string.Empty;
var dotNetObjRef = DotNetObjectReference.Create(this);
await _jsruntime.InvokeVoidAsync("callWebService", dotNetObjRef, "OutputMessage");
_stopWaitHandle.WaitOne();
return _message;
}
[JSInvokable]
public async Task OutputMessage(string message)
{
_message = message;
Console.WriteLine($"**** OutputMessage {message}");
_stopWaitHandle.Set();
}
}
}
The javascript:
async function callWebService(instance, method) {
instance.invokeMethodAsync(method, "start");
var wsUri = "wss://127.0.0.1:80/Test/";
var websocket = new WebSocket(wsUri);
console.log("websocket has been setup");
websocket.onopen = function (e) {
console.log("websocket connected");
websocket.send("Hellow world")
};
websocket.onclose = function (e) {
instance.invokeMethodAsync(method, "closed");
console.log("websocket closed");
};
websocket.onmessage = function (e) {
console.log("websocket got message" + e.data);
instance.invokeMethodAsync(method, e.data);
websocket.close();
};
websocket.onerror = function (e) {
console.log("websocket error");
instance.invokeMethodAsync(method, "error");
websocket.close();
};
}
You will need to add this to the startup in ConfigureServices:
services.AddScoped<IService1, Service1>();
You will need to add the following to your _Hosts.cshtml:
<script src="~/scripts/Javascript.js"></script>
EDIT: it works when I try this without an injected service (putting the call and callback right in the razor page). Hrmmm.