I'm using SignalR RC2, this is my hub
public class ImgHub : Hub
{
public void Create(string guid)
{
Groups.Add(Context.ConnectionId, "foo");
}
public void SendMsg(string msg)
{
Clients.Group("foo").send(msg);
}
}
I have a console application and a webapplication (asp.net webforms) that connect to this hub. the console application works just as I would expect, the problem is in the Javascript part. The "send" callback doesn't fire when I'm using Clients.Group in SendMsg, if I change SendMsg to this
public void ShareImage(byte[] image, string guid)
{
Clients.All.ReceiveImage(image);
}
it works. Here is the Javascript code
<script src="Scripts/jquery-1.7.1.min.js"></script>
<script src="Scripts/jquery.signalR-1.0.0-rc2.min.js"></script>
<script src="http://localhost:4341/signalr/hubs/" type="text/javascript"></script>
<script type="text/javascript">
var mainHub;
$(function () {
$.connection.hub.url = 'http://localhost:4341/signalr';
// Proxy created on the fly
mainHub = $.connection.imgHub;
mainHub.client.send = function (msg) {
alert(msg);
};
// Start the connection
$.connection.hub.start(function() {
mainHub.server.create('vanuit den JS');
})
.done(function() {
$('#msgButton').click(function() {
mainHub.server.sendMsg("msg from JS");
});
});
});
</script>
as you can see in the JS code, I also have a button on the page that calls the SendMsg function, the message does arrive on the console application so I would guess that the JS client is correctly registered in the SignalR group.
I'm no JS specialist so I hope someone that knows more about it then I do can help me out here.
It's because you need to enable rejoining groups in global asax.
GlobalHost.HubPipeline.EnableAutoRejoiningGroups();
There's more detail about that here:
http://weblogs.asp.net/davidfowler/archive/2012/11/11/microsoft-asp-net-signalr.aspx
This method call is going away for 1.0 RTM but for now you need to do it.
One of the reasons why your send function may not be executing is because by the time you are allowing a call to sendMsg on the client the client may not be in the group "foo" yet.
In your $.connection.hub.start you're registering a function to be called when start has completed, but you're also then registering another function to be called once start has completed via the .done. Therefore, what's happening is both functions are firing almost simultaneously. So when the sendMsg function is available to be called you may not have been successfully added to the group.
Here's how you can fix that problem:
$.connection.hub.start().done(function() {
mainHub.server.create('vanuit den JS').done(function() {
$('#msgButton').click(function() {
mainHub.server.sendMsg("msg from JS");
});
});
});
Essentially I'm waiting until the group join has completed successfully until allowing a sendMsg to go through.
I know that this is a long shot answer since you're probably waiting a significant amount of time after the connection has been started and still nothings coming over the wire but I'm unable to replicate the behavior on my end.
If my fix above does not work you should ensure that your server side functions are being called by setting break points.
Related
Whenever I try to execute JavaScript through C# using CefSharp (Stable 57.0), I get an error. I am simply trying to execute the alert function, so I can make sure that works and later test it out with my own function. However, I seem to be getting errors trying to do so.
public partial class WebBrowserWindow : Window
{
public WebBrowserWindow()
{
InitializeComponent();
webBrowser.MenuHandler = new ContextMenuHandler();
webBrowser.RequestHandler = new RequestHandler();
}
//Trying to execute this with either method gives me an error.
public void ExecuteJavaScript()
{
//webBrowser.GetMainFrame().ExecuteJavaScriptAsync("alert('test')");
//webBrowser.ExecuteScriptAsync("alert('test');");
}
}
I have tried both ways of executing the script.
The first one:
webBrowser.GetMainFrame().ExecuteJavaScriptAsync("alert('test')");
Gives me this error:
The second:
webBrowser.ExecuteScriptAsync("alert('test');");
Gives me this error:
My objective is to create a C# function that can execute a JavaScript function in my CefSharp Browser.
I tried many links/references and there weren't that many on stack overflow. I also read The FAQ for CefSharp and couldn't find any simple examples that allow me to execute JavaScript at will through C#.
In addition, I've verified the events where the Frame is loaded (it finishes loading), and unloaded (it does not unload), and if the webbrowser is null (which it's not), and the message from the:
webBrowser.GetMainFrame().ExecuteJavaScriptAsync("alert('test')");
still causes the first error to occur.
I tested for GetMainFrame(). It always returns null. ALWAYS. Doesn't matter how long I wait, or what conditions I check for.
IMPORTANT
I forgot to add one crucial piece of information, I have 2 assemblies in my project. Both of them compile into separate executables:
Helper.exe
Main.exe
main.exe has a window "CallUI" that, when a button gets clicked, it executes the method I created "ExecuteJavaScript()", which is inside of my window "BrowserWindow". The CallUI window is declared and initialized in Helper.exe.
So basically I am trying to use a separate program to open a window, click a button that calls the method and execute javascript. So I think because they are different processes, it tells me the browser is null. However, when I do it all in Main.exe it works fine. Is there a workaround that allows me to use the separate process to create the window from Helper.exe and execute the Javascript from Main.exe?
It has come to my attention that I was handling the problem the wrong way.
My problem, in fact, doesn't exist if it's just a single process holding all the code together. However, the fact that my project has an executable that was trying to communicate with another was the problem. I actually never had a way for my helper.exe to talk to my main.exe appropriately.
What I learned from this is that the processes were trying to talk to each other without any sort of shared address access. They live in separate address spaces, so whenever my helper.exe tried to execute that javascript portion that belonged in Main.exe, it was trying to execute the script in an uninitialized version of a browser that belonged in its own address space and not main.exe.
So how did I solve that problem? I had to include an important piece that allowed the helper.exe process to talk to the main.exe process. As I googled how processes can talk to each other, I found out about MemoryMappedFiles. So I decided to implement a simple example into my program that allows Helper.exe to send messages to Main.exe.
Here is the example. This is a file I created called "MemoryMappedHandler.cs"
public class MemoryMappedHandler
{
MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen("mmf1", 512);
MemoryMappedViewStream stream;
MemoryMappedViewAccessor accessor;
BinaryReader reader;
public static Message message = new Message();
public MemoryMappedHandler()
{
stream = mmf.CreateViewStream();
accessor = mmf.CreateViewAccessor();
reader = new BinaryReader(stream);
new Thread(() =>
{
while (stream.CanRead)
{
Thread.Sleep(500);
message.MyStringWithEvent = reader.ReadString();
accessor.Write(0, 0);
stream.Position = 0;
}
}).Start();
}
public static void PassMessage(string message)
{
try
{
using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("mmf1"))
{
using (MemoryMappedViewStream stream = mmf.CreateViewStream(0, 512))
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(message);
}
}
}
catch (FileNotFoundException)
{
MessageBox.Show("Cannot Send a Message. Please open Main.exe");
}
}
}
This is compiled into a dll that both Main.exe and Helper.exe can use.
Helper.exe uses the method PassMessage() to send the message to a Memory Mapped File called "mmf1". Main.exe, which must be open at all times, takes care of creating that file that can receive the messages from Helper.exe. I sends that Message to a class that holds that message and every time it receives it, it activates an event.
Here is what the Message class looks like:
[Serializable]
public class Message
{
public event EventHandler HasMessage;
public string _myStringWithEvent;
public string MyStringWithEvent
{
get { return _myStringWithEvent; }
set
{
_myStringWithEvent = value;
if (value != null && value != String.Empty)
{
if (HasMessage != null)
HasMessage(this, EventArgs.Empty);
}
}
}
}
Finally, I had to initialize Message in my WebBrowserWindow class like this:
public partial class WebBrowserWindow : Window
{
public WebBrowserWindow()
{
InitializeComponent();
webBrowser.MenuHandler = new ContextMenuHandler();
webBrowser.RequestHandler = new RequestHandler();
MemoryMappedHandler.message.HasMessage += Message_HasMessage;
}
private void Message_HasMessage(object sender, EventArgs e)
{
ExecuteJavaScript(MemoryMappedHandler.message.MyStringWithEvent);
}
public void ExecuteJavaScript(string message)
{
//webBrowser.GetMainFrame().ExecuteJavaScriptAsync("alert('test')");
//webBrowser.ExecuteScriptAsync("alert('test');");
}
}
And now it allows me to execute the javascript I need by sending a message from the Helper.exe to the Main.exe.
Have you tried this link? Contains a snippet that checks if the browser is initialised first.
cefsharp execute javascript
private void OnIsBrowserInitializedChanged(object sender, IsBrowserInitializedChangedEventArgs args)
{
if(args.IsBrowserInitialized)
{
browser.ExecuteScriptAsync("alert('test');");
}
}
After hours of googling i found only one sample about event source using for asp.net (Not MVC). Firstly i must say i want to learn it and my final goal is to creating a friendly poker website. SignalR is very very good for my purpose but i do not want to use this because i heard:
SignalR is bad in performance
isn't it?(i hope not). My problem is when server sends response to client it sends the previous text not current:
$("#btnListen").click(function ()
{
var source = new EventSource('SSEHandler.ashx');
source.addEventListener("open", function (event)
{
$('#headerDiv').append('Latest 5 values');
}, false);
source.addEventListener("error", function (event)
{
if (event.eventPhase == EventSource.CLOSED)
{
$('#footerDiv').append('Connection Closed!');
}
}, false);
source.addEventListener("message", function (event)
{
console.log(event.data);
}, false);
});
And this is SSEHandler:
public class SSEHandler : IHttpHandler
{
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
HttpResponse Response;
Response = context.Response;
Response.ContentType = "text/event-stream";
Response.Write(string.Format("data: {0}\n\n", "first"));
Response.Flush(); //client has no response received yet
Response.Write(string.Format("data: {0}\n\n", "second"));
Response.Flush(); //now client get "first".
Response.Close();
}
}
After executing this cods client console only have "first". And if i add this to end of SSEHandler:
Response.Write(string.Format("data: {0}\n\n", "third"));
Response.Flush();
In client console we have "first", "Second".
Thanks for reading my long post.
Its been a while since you asked the question, but after struggling with this for a while myself I found a workaround I thought could be useful to share for others having the same issue.
Simply adding a comment (line that starts with colon) after each event will make the events appear when they should.
Response.Write("data: first\n\n")
Response.Write(":comment\n")
Response.Write("data: second\n\n")
Response.Write(":comment\n")
Note: The problem is more apparent when working with events that comes dynamically, since at that point the first event wont produce anything on the client, then when the second event hits, the first is displayed in the client. And this goes on with second and third etc..
I am new to signalR.I am developing a simple application in signalR. The Requirement is ,the signalR need to be update the current time to client repeatedly with some time delay.While i am starts running, the code i get server response for a time only.it's not repeated again and again. i need to callback the sameHubclass for update the current time to client again and again!
here is my Code:-
Javascript Client Code:-
<body>
<div class="container">
<input type="hidden" id="name" />
</div>
<script src="Scripts/jquery-1.6.4.min.js"></script>
<script src="Scripts/jquery.signalR-2.2.1.min.js"></script>
<script src="signalr/hubs"></script>
<script type="text/javascript">
$(function () {
var chat = $.connection.timeHub;
chat.client.broadcastMessage = function (name,current) {
var now = current;
console.log(current);
$('div.container').append('<p><strong>'+name+"="
+ now + '</strong></p>');
};
$("#name").val(prompt("Enter the UserName", ""));
$.connection.hub.start().done(function () {
chat.server.send($("#name").val());
});
});
</script>
</body>
HubClass:-
public class timeHub : Hub
{
public void send(string name)
{
while(true)
{
string current = DateTime.Now.ToString("HH:mm:ss:tt");
Clients.All.broadcastMessage(name,current);
Console.WriteLine(current);
Console.ReadLine();
System.Threading.Thread.Sleep(3000);
send(name);
}
}
}
MyOwin Startup Class:-
[assembly: OwinStartup(typeof(Time.Startup))]
namespace Time
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
How do i add callback functionality for my HubClass in Javascript Client Code in SignalR.
here is my current Output without callback function and timedelay:-
but the signalR and .net client application or working fine.I need to time delay for hubclass and callback the samehub class periodically?
Is it possible to callback the same hub class in server with some time delay?
For that i am added, time delay in hubclass. and i callback the hubclass in server .It won't work.Could anyone provide me an solution for this?
Ideally you would want to use a timer that calls the broadcastMessage method with the current time. There are some issues with your send hub method though. Also SignalR instantiates the hub class per each call and state is not maintained.
In my MVC view I need to get razor c# code to execute a javascript function at unpredictable times, way after the page has loaded.
I have used a thread to simulate unpredictableness but ultimately instead of the thread it will be a WCF callback method that raises an event which runs the helper, but to eliminate session issues I have used the thread.
Javascript to execute:
<script type="text/javascript">
function DisplayNews(news) {
alert(news);
}
</script>
Helper that runs the javascript (because sticking this directly in the below thread didn't work)
#helper UpdateNews(string news)
{
<script>
DisplayNews(news);
</script>
}
Thread that simulates unpredictableness/post page loading or non user invoked events
#{
System.Threading.Thread T = new System.Threading.Thread(new System.Threading.ThreadStart(delegate
{
while (true)
{
System.Threading.Thread.Sleep(5000);
UpdateNews("Some cool news");
}
}));
T.Start();
}
If I stick a break point at UpdateNews("Some cool news"); I can see that it gets hit every 5 seconds as it should, but thats as far as it gets, nothing else happens. I can't stick a break point in the helper or the Javascript so I can't see where it stops working after that.
Is this going to work at all or is there another way I should be approaching this?
Any help would be greatly appreciated.
In server side code you can call an client function...
Razor executed in server side and javascript is in client side.that mean when you get server response it's created by razor code in server side and now you can just use javascript in client side
I may be misunderstanding what you are trying to do but you can have javascript that will run on page load that will be wrapped in a set timeout with a random millisecond period.
Something like this:
<script>
window.onload = function() {
setTimeout(function() {}, 1000); // this will run 1 second after page load
}
</script>
simply randomize the number being passed as the second parameter to setTimeout and your javascript will run at a random time after the page loads.
I am using Ajax's EnablePageMethods way to call server side code using javascript. The problem is that in IE8 the page automatically refreshes after the ajax call has been completed i.e. the server side function has been executed successfully. I want the same to happen with Chrome and Firefox but it doesnt refresh the page once the server side function has been executed.
Any idea or suggestion how to achieve that?
I am using this way to call server side code from Javascript --
http://www.codeproject.com/KB/ajax/Ajax_Call_using_AjaxNet.aspx
this is the javascript function:
function editNode(note) {
PageMethods.deleteNote(note);
}
and this is the server side function:
[System.Web.Services.WebMethod]
public static void deleteNote(int noteId)
{
string test = noteId.ToString();
Note note = new Note(noteId);
note.IsDeleted = true;
note.update();
}
this is where i am calling the javascript event:
<a href='myPageName.aspx' onclick='javascript:editNode(1);return false;'>Delete</a>
Here is how I did it:
function editNode(note) {
PageMethods.deleteNote(note,OnSuccess,OnFailure);
}
function OnSuccess() {
if (!navigator.appName == 'Microsoft Internet Explorer')
{
window.location.href=window.location.href;
}
}
function OnFailure(error) {
}
I found this solution on this link:
http://www.codedigest.com/CodeDigest/80-Calling-a-Serverside-Method-from-JavaScript-in-ASP-Net-AJAX---PageMethods.aspx