Unable to send a message to client using signalr in firefox - javascript

startup class:
using Owin;
using Microsoft.Owin;
using Microsoft.AspNet.SignalR;
[assembly: OwinStartup(typeof(ESimSolFinancial.Startup))]
namespace ESimSolFinancial
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
// Any connection or hub wire up and configuration should go here
app.MapSignalR("/signalr", new HubConfiguration());
}
}
}
Hub Class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using Microsoft.AspNet.SignalR;
namespace ESimSolFinancial.Hubs
{
public class ProgressHub : Hub
{
public static void SendMessage(string msg,int nCount)
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ProgressHub>();
hubContext.Clients.All.broadcastMessage(string.Format(msg), nCount);
}
}
}
in a js file i have this function:
function InitializeProgressBar() {
ProgressBarShow();
var progressNotifier = $.connection.progressHub;
progressNotifier.client.broadcastMessage = function (message, count) {
UpdateProgressBar(message, count);
};
$.connection.hub.url = "/signalr";
$.connection.hub.start({ transport: ['webSockets', 'longPolling'] }).done(function () {
//progressNotifier.client.broadcastMessage('Opening Connection',0);
});
}
it is called on a click event
the click event invokes an action result in which i have this code:
Thread.Sleep(5000);
ProgressHub.SendMessage("Getting Ledger Data", 10);
to update a progressbar after long processes finish.
the messages are sent correctly in chrome and IE but firefox does not receive these messages accordingly. UpdateProgressBar(message, count); does not get invoked. it works sometimes when i open firebug and stop execution for a long time.
i thought it was because the long processes were not long enough, so i increased the sleep time but that was not the case.
i don't understand what i'm doing wrong here. any help is appreciated.
UPDATE:
the actionresult is of the page where click event is. it seems to work only after the application has just started. after that firefox refuses to receive those messages.

Have you called server function for click event in js
progressNotifier.server.SendMessage(msg,count);
You can modify client code ... by calling server function
function InitializeProgressBar() {
ProgressBarShow();
var progressNotifier = $.connection.progressHub;
progressNotifier.client.broadcastMessage = function (message, count) {
UpdateProgressBar(message, count);
};
$.connection.hub.url = "/signalr";
$.connection.hub.start({ transport: ['webSockets', 'longPolling']
}).done(function () {
//Call to server function(SendMessage) made .This fuction broadcasts to all clients
//by calling client side(broadcast message ) function of all users
progressNotifier.server.SendMessage(msg,count);
//progressNotifier.client.broadcastMessage('Opening Connection',0);
});
}
Please try this.I cant run the program in an application. But this is how signal R works.One client calls a server function on an event(or server replies on no call but some logic) and the server broadcasts realtime notifications to selected groups,or selected users or all of them(in client side).
$('#id').click(function(){
progressNotifier.server.SendMessage(msg,count);
});
Server function has to be called

Related

webSocket.send() inside webSocket.onopen always fails

I'm starting with WebSockets and, to try things off, I built a minuscule WebSocket server in C# (using WebSocketSharp) and an html as a client to connect to it.
On the client I have this code:
const webSocket = new WebSocket("ws://localhost:51036/test");
webSocket.onopen = e => {
webSocket.send("hello :D");
console.log("Socket connection opened!");
}
This send() call never works — it sometimes result in an exception in the C# server, most other times it is just ignored as if nothing was ever received on the server's end. However, any send() I call afterwards (e.g. with a button) works fine, and send() inside onopen also works fine if I place it inside a timeout of just 200ms. If I don't call any send() onopen, and just call it later via a button, it always works fine (so it's not a 'first call always fails' issue).
On the C# side, the code is very simple:
public class TestWS : WebSocketBehavior {
protected override void OnMessage (MessageEventArgs e) {
System.Diagnostics.Debug.WriteLine($"Client message: {e.Data}");
Send($"String length: {e.Data.Length} [msg received: {e.Data}]");
}
}
public static class Sockets {
public const string SERVER_ROUTE = "ws://localhost:51036";
private static WebSocketServer socket;
public static void Start () {
socket = new WebSocketServer(SERVER_ROUTE);
socket.AddWebSocketService<TestWS>("/test");
socket.Start();
System.Diagnostics.Debug.WriteLine($"Server started on {SERVER_ROUTE}");
}
public static void Stop () {
socket.Stop();
}
}
The exception in question is this one:
2021-09-06 19:59:06|Fatal|WebSocket.<startReceiving>b__175_2:0|WebSocketSharp.WebSocketException: The header of a frame cannot be read from the stream.
at WebSocketSharp.WebSocketFrame.processHeader(Byte[] header)
at WebSocketSharp.WebSocketFrame.<>c__DisplayClass73_0.<readHeaderAsync>b__0(Byte[] bytes)
at WebSocketSharp.Ext.<>c__DisplayClass55_0.<ReadBytesAsync>b__0(IAsyncResult ar)

Switching from ChromeBrowser.RegisterAsyncJsObject to ChromeBrowser.JavascriptObjectRepository.Register does not let me handle function calls

In an older CEF version (73.1.13), I register an object with (C#)
ChromeBrowser.RegisterAsyncJsObject("extInterop", new CommandObject(this),
new BindingOptions() {CamelCaseJavascriptNames = false});
The webpage I have loaded uses javascript to find the extInterop object and calls a function inside it.
It will be received in the CommandObject class (C#).
using System.Diagnostics;
namespace foo
{
public class CommandObject
{
public void executeCommand(string command, object value)
{
Debug.WriteLine(command + " " + value.ToString());
}));
}
}
and the web page uses the javascript
window.extInterop.executeCommand("thecommand", 0);
This works fine, the command is received as I expect in the CommandObject.
However, when I have upgraded CEF to a newer version (85.3.13), I get a System.NotImplementedException and the message containing a link (https://github.com/cefsharp/CefSharp/issues/2990) where instructions on how to replace the call can be found. I tried to replace it with
ChromeBrowser.JavascriptObjectRepository.Register("extInterop",
new CommandObject(this), isAsync: true, options: BindingOptions.DefaultBinder);
But messages sent as before from the javascript end are never delivered in the C# end.
Why not?

How to connect from JavaScript to SignalR in Cross domain?

I have an signalR application which listen from different clients such as C#, JavaScript later we may extend it for other technologies. My signalR server is in console Application. right now I created .net client which are successfully connected to server. I tried a lot to write a javascript client but i didn't succeed. please help me to fix it.
1. I created server.Js file by running the command signalr.exe ghp /path: and include it in Js page
2. I am using 2.0.1 version for Owin and SignalR
3. tried with server URL http://127.0.0.1:8088/signalr and http://127.0.0.1:8088
Here is my server code
[assembly: Microsoft.Owin.OwinStartup(typeof(Program.Startup))]
namespace SignalRServer
{
internal class Program
{
private static IDisposable SignalR;
private static void Main(string[] args)
{
string url = "http://127.0.0.1:8088/signalr";
SignalR = WebApp.Start(url);
Console.ReadKey();
}
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
[HubName("MyHub")]
public class MyHub : Hub
{
public void Send(string name, string message)
{
Console.WriteLine($"{name}:{message}");
Clients.All.addMessage(name, message);
}
}
}
}
My JS Client Code
var con = $.hubConnection('http://127.0.0.1:8088');
alert(con);
var hub = con.createHubProxy('MyHub');
con.start().done(function () {
alert('Now connected, connection ID=' + connection.id);
});
hub.invoke('Send');

Injecting javascript using LoadUrl fails in Android WebView for SDK 24+

I am trying to inject a javascript namespace with function from App to Android WebView
NOTE: I do not have any control on the actual source being loaded on WebView apart from the below script. I am working in Xamarin so the Android code is C#
So there are two major components that I am using:
(function() {
console.log("Loading JS Bindings");
function addOnClickHandler () {
$(document).ready(function () {
if (window.InjectedNamespace) { // check InjectedNamespace namespace exists
var onClickHandler = window.InjectedNamespace.handleOnClick;
if (typeof onClickHandler === 'function') {
$(":button, a").each(function (idx) {
$(this).click(function() {
onClickHandler("click!");
});
});
} else {
console.error('missing onclick handler');
}
} else {
console.error('missing InjectedNamespace namespace');
}
});
}
})();
Above script which will be added by the third-party, which will attach click function to all <button> and <a> tags.
Below namespace will be injected from the App side
var InjectedNamespace={handleOnClick:function(a){Internal.handleOnClickEvent(a)}};
On App side I have this Javascript interface object
class JSInterfaceObject : Java.Lang.Object
{
readonly CustomWebView View;
string Data;
public JSInterfaceObject(CustomWebView view)
{
View = view;
}
[Export]
[JavascriptInterface]
// only methods exposed with annotation [JavascriptInterface] are exposed to javascript
public void handleOnClickEvent(string data)
{
Log.ForContext("TAG", TAG).Debug("handleOnClickEvent: " + data);
if(View.OnClick != null)
{
View.OnClick(data);
}
}
}
And this interface is added to webview using
AddJavascriptInterface(new JSInterfaceObject(this), "Internal");
And in OnPageStarted I am injecting the javascript using
webview.LoadUrl("javascript:"+"var IM={handleOnClick:function(a){Internal.handleOnClickEvent(a)}};");
This setup work fine for Android SDK < 24. But for Webview in SDK >=24 the script always errors out with missing InjectedNamespace namespace, which implies the LoadUrl in OnPageStarted failed!
This check is done in $(document).ready in the script.
I found this note in "Android 7.0 for Developers" which says
"Starting with apps targeting Android 7.0, the Javascript context will
be reset when a new page is loaded. Currently, the context is carried
over for the first page loaded in a new WebView instance.
Developers looking to inject Javascript into the WebView should
execute the script after the page has started to load."
So tried to add the javascript injection code after the page started loading but got the same error. Also tried using the WebView.EvaluateJavascript() but error persists.
The error disappers if I change my TargetSDK to <=23.

Excecuting some JavaScript code makes Android web application hang

I am developing Android web application by using PhoneGap, it works well at most part, but sometime when I want to download or upload files, the application hang up and does not respond to any touch event till the task is finished. I am going to describe more about code I have written;
HTML code:
<a id="download">Download/a>
JavaScript code:
$("#download").click(function() {
/*Here I used a plugin which is a Java class, and call this plugin and pass the required parameters*/
var data = [id, fileName];
window.download(callServiceSuccessCallBack,
callServiceFailCallBack, "download", data);
});
The XML config file which register the plugin here:
<plugins>
<plugin name="DowloadFilePlugin" value="com.example.plugin.DowloadFilePlugin" />
</plugins>
Java code:
#Override
public boolean execute(String action, JSONArray args,
CallbackContext callbackContext) throws JSONException {
if ("download".equals(action)) {
// do something
}
return true;
}
When I press the button then the application hanged till the file downloaded.
If anyone knows about this problem please let me know how to solve, in addition i also tried window.setTimeout(code, 0); did not solve the problem.
Thanks in advance!
Try to use a setTimeout with a delay of 0 or 100ms to start your action :
$("#download").click(function() {
/*Here I used a plugin which is a Java class, and call this plugin and pass the required parameters*/
var data = [id, fileName];
setTimeout(function(){
window.download(callServiceSuccessCallBack,
callServiceFailCallBack, "download", data);
},0);
});
I solve the problem by adding thread in JAVA code as below:
#Override
public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
if ("beep".equals(action)) {
final long duration = args.getLong(0);
cordova.getThreadPool().execute(new Runnable() {
public void run() {
// do something....
}
});
return true;
}
return false;
}

Categories