I am very new to the term SignalR . I was try to configure the signalR into my empty website and Added following code.
In App_Code
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(Super.App_Code.Startup))]
namespace Super.App_Code
{
public class Startup
{
public static void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
and the hub class Inside App_Code
namespace Super.App_Code
{
[HubName("toastHub")]
public class ToastHub : Hub
{
public void BroadcastToast(string type ,string msg)
{
Clients.All.sendToast(type , msg);
}
}
}
and in Default.aspx
<head runat="server">
<title></title>
<link rel="stylesheet" href="content/toastr.min.css" />
<script src="Scripts/jquery-1.6.4.js" type="text/javascript"></script>
<script src="Scripts/jquery.signalR-2.4.1.js" type="text/javascript"></script>
<script src="Scripts/toastr.min.js" type="text/javascript"></script>
<script src="signalr/hubs" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#SuccessLink").click(function () {
console.log("Success Click");
$.connection.toastHub.client.broadcastToast('success', 'you have done');
});
$("#ErrorLink").click(function () {
console.log("Error Click");
$.connection.toastHub.client.broadcastToast("error", "you have not done");
});
$.connection.hub.start().done(function () {
console.log('SignalR connected');
})
.fail(function (data) {
console.log('SignalR failed to connect: ' + data);
});
$.connection.toastHub.client.sendToast = function (type, msg) {
console.log("sendToast Called");
toastr[type](msg);
};
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<a id="SuccessLink" style="color: lightgreen">Success Toast</a><br />
<a id="ErrorLink" style="color: red">Error Toast</a>
</div>
</form>
</body>
</html>
but when i run my website the javascript console says this when click on one of the tag
SignalR connected
Default.aspx:20 Success Click
Default.aspx:21 Uncaught TypeError: $.connection.toastHub.client.broadcastToast is not a function
at HTMLAnchorElement.<anonymous> (Default.aspx:21)
at HTMLAnchorElement.handle (jquery-1.6.4.js:3001)
at HTMLAnchorElement.eventHandle (jquery-1.6.4.js:2635)
Am i doing anything wrong please help me any help would be greatful .i am totally new to SignalR .
signalr/hub
if (typeof ($.signalR) !== "function") {
throw new Error("SignalR: SignalR is not loaded. Please ensure jquery.signalR-x.js is referenced before ~/signalr/js.");
}
var signalR = $.signalR;
function makeProxyCallback(hub, callback) {
return function () {
// Call the client hub method
callback.apply(hub, $.makeArray(arguments));
};
}
function registerHubProxies(instance, shouldSubscribe) {
var key, hub, memberKey, memberValue, subscriptionMethod;
for (key in instance) {
if (instance.hasOwnProperty(key)) {
hub = instance[key];
if (!(hub.hubName)) {
// Not a client hub
continue;
}
if (shouldSubscribe) {
// We want to subscribe to the hub events
subscriptionMethod = hub.on;
} else {
// We want to unsubscribe from the hub events
subscriptionMethod = hub.off;
}
// Loop through all members on the hub and find client hub functions to subscribe/unsubscribe
for (memberKey in hub.client) {
if (hub.client.hasOwnProperty(memberKey)) {
memberValue = hub.client[memberKey];
if (!$.isFunction(memberValue)) {
// Not a client hub function
continue;
}
// Use the actual user-provided callback as the "identity" value for the registration.
subscriptionMethod.call(hub, memberKey, makeProxyCallback(hub, memberValue), memberValue);
}
}
}
}
}
$.hubConnection.prototype.createHubProxies = function () {
var proxies = {};
this.starting(function () {
// Register the hub proxies as subscribed
// (instance, shouldSubscribe)
registerHubProxies(proxies, true);
this._registerSubscribedHubs();
}).disconnected(function () {
// Unsubscribe all hub proxies when we "disconnect". This is to ensure that we do not re-add functional call backs.
// (instance, shouldSubscribe)
registerHubProxies(proxies, false);
});
proxies['toastHub'] = this.createHubProxy('toastHub');
proxies['toastHub'].client = { };
proxies['toastHub'].server = {
};
return proxies;
};
signalR.hub = $.hubConnection("/signalr", { useDefaultPath: false });
$.extend(signalR, signalR.hub.createHubProxies());
}(window.jQuery, window));
Something is not correctly initialized with your SignalR project, I guess accessing a hubContext should have a Dependency Injector in your startup.cs. But doing context injection with DI for SignalR is an advanced level problem.
However, please try this minimal sample, if it's working for you: https://github.com/bezzad/MVC-SignalR-2
Looks to me like you need to just change the calls to broadcastToast from client to server. As that method is in the Hub and so requires the server instead.
$.connection.toastHub.client.broadcastToast
To
$.connection.toastHub.server.broadcastToast
Related
I have called actionresult function from JavaScript using AJAX when a button is clicked:
<script type="text/javascript">
$('.btn-SelectStudent').on('click', function () {
$('input:radio').each(function () {
if ($(this).is(':checked')) {
var id = $(this).val();
$.ajax({
url: '#Url.Action("ParseSearchLists", "Upload")',
data: { studentId: id }
}).success(function (data) {
alert('success');
});
}
else {
// Or an unchecked one here...
}
});
return false;
})
</script>
Inside the UploadController.cs:
[HttpPost]
public ActionResult ParseSearchLists(int studentId)
{
SearchModel searchModel = ApplicationVariables.searchResults.Where(x => x.StudentId == studentId).ToList().First();
TempData["SearchModel"] = searchModel;
return RedirectToAction("UploadFile", "Upload");
}
public ActionResult UploadFile()
{
searchModel = TempData["SearchModel"] as SearchModel;
return View(searchModel); //debug point hits here.
}
Inside UploadFile(), I have returned View and it should load another view. But I get only "success" in alert but no new view is loaded. I assume, view should be loaded.
You're making an "AJAX" call to the server, meaning your request is running outside of the current page request and the results will be returned to your success continuation routine, not to the browser's rendering engine. Essentially the data parameter of that routine is probably the entire HTML response of your UploadFile view.
This is not what .ajax is used for. It is for making asynchronous requests to the server and returning data (usually JSON or XML) to your javascript to be evaluated and displayed on the page (this is the most common use anyway).
I can't see your HTML, but wouldn't you be better off just using an <a> anchor (link) tag and sending your student ID on the query string? It's hard to tell what you are attempting to do but your views' HTML (.cshtml) will never be displayed using the code you have now.
It seems, you are not loading view returned to div on ajax success. replace #divname with your div in your code in below code. i hope this helps to resolve your issue
<script type="text/javascript">
$('.btn-SelectStudent').on('click', function () {
$('input:radio').each(function () {
if ($(this).is(':checked')) {
var id = $(this).val();
$.ajax({
url: '#Url.Action("ParseSearchLists", "Upload")',
dataType: "html",
data: { studentId: id }
}).success(function (data) {
$('#divName').html(data); // note replace divname with your actual divname
});
}
else {
// Or an unchecked one here...
}
});
return false;
})
</script>
[HttpPost]
public ActionResult ParseSearchLists(int studentId)
{
SearchModel searchModel = ApplicationVariables.searchResults.Where(x => x.StudentId == studentId).ToList().First();
return View("UploadFile",searchModel); //debug point hits here.
}
I have page which contains three panels for employee attendence, salary, production. I have to update the panels at real time by SignalR.
My hub class
public class MessagesHub : Hub
{
private string ConnectionString = ConfigurationManager.ConnectionStrings["database"].ToString();
[HubMethodName("sendMessages")]
public void SendMessages()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<MessagesHub>();
context.Clients.All.updateMessages();
}
}
In Controller
public ActionResult Panels()
{
...code..
return Partial("_panelData", model);
}
The partial page has the panels along with data to display.
In the main View page(Panels), at script tag
<script>
$(function () {
// Declare a proxy to reference the hub.
var notifications = $.connection.messagesHub;
//debugger;
// Create a function that the hub can call to broadcast messages.
notifications.client.updateMessages = function () {
getData()
};
// Start the connection.
$.connection.hub.start().done(function () {
getData();
}).fail(function (e) {
alert(e);
});
});
function getData() {
$.ajax({
url: '/PanelController/Panels',
type: 'GET',
dataType: 'html'
}).success(function (result) {
$('.panel').html(result)
}).error(function () {
window.console.log("failure");
});
}
</script>
It works fine when the page loads. But i also want it to load the data at every 1 min time interval.
Thanks in advance
Maybe I missunderstood but for me SignalR is useless there. Something like this should work :
$(function() {
getData();
});
function getData() {
$.ajax({
url: '/PanelController/Panels',
type: 'GET',
dataType: 'html'
}).success(function(result) {
$('.panel').html(result)
window.setTimeout(getData(), 60000)
}).error(function() {
window.console.log("failure");
});
}
If you want to keep signalr the only things to do is to add this:
window.setTimeout(getData(), 60000) inside the callback of the getData function()
I was pointed to this GITHub sample code by David Fowler himself to track SignalR users and states. I have implemented all of it and it works great except I can't figure out the displaying of Hub connection state changes. I have this which doesn't seem to work. Does anyone know why?
!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<style>
#state {
width: 20px;
height: 50px;
}
</style>
</head>
<body>
<h3 id="msg"></h3>
<div id="state"></div>
<script src="../Scripts/jquery-1.10.2.min.js"></script>
<script src="../Scripts/jquery.signalR-2.0.2.min.js"></script>
<script src="signalr/hubs"></script>
<script>
$(function () {
var userTracking = $.connection.alphaHub;
// Need at least one callback for events to be raised on the hub
userTracking.client.void = function () { };
$.connection.logging = true;
$.connection.hub.stateChanged(function (change) {
if (change.newState === $.signalR.connectionState.connected) {
$('#state').css('background-color', 'green');
} else if (change.newState === $.signalR.connectionState.reconnecting) {
$('#state').css('background-color', 'yellow');
} else if (change.newState === $.signalR.connectionState.disconnected) {
$('#state').css('background-color', 'red');
}
});
$.connection.hub.disconnected(function () {
setTimeout(function () {
$.connection.hub.start();
}, 1000);
});
});
</script>
</body>
</html>
My Hub is shown partially here:
public class AlphaHub : Hub
{
public override async Task OnConnected()
{
try
{
var name = Context.User.Identity.Name;
using (savitasEntities2 entities = new savitasEntities2())
{
var user = entities.SUsers
.Include(u => u.SConnections)
.SingleOrDefault(u => u.UserName == name);
if (user == null)
{
user = new SUser
{
UserName = name,
SConnections = new List<SConnection>()
};
entities.SUsers.Add(user);
}
user.SConnections.Add(new SConnection
{
ConnectionID = Context.ConnectionId,
UserAgent = Context.Request.Headers["User-Agent"],
LastActivity = DateTimeOffset.UtcNow
});
// entities.SaveChanges();
await entities.SaveChangesAsync();
}
}
public override async Task OnDisconnected()
{
try
{
using (savitasEntities2 db = new savitasEntities2())
{
var connection = await db.SConnections.FindAsync(Context.ConnectionId);
db.SConnections.Remove(connection);
await db.SaveChangesAsync();
}
}
catch (Exception ex)
{
c.LogError(ex.Message, "AlphaHub.cs" + " - " + this.GetType().FullName + "." + System.Reflection.MethodBase.GetCurrentMethod().Name);
}
}
Looks like your hubs can't be found.
Change:
<script src="signalr/hubs"></script>
to:
<script src="~/signalr/hubs"></script>
bonsai docs “Communication” section (http://docs.bonsaijs.org/overview/Communication.html) has the following example which runs everywhere, except IE9:
<script src="http://cdnjs.cloudflare.com/ajax/libs/bonsai/0.4/bonsai.min.js"></script>
<div id="movie"></div>
<script>
var movie = bonsai.run(
document.getElementById('movie'),
{
code: function() {
// receive data from the other side
var text = new Text().addTo(stage);
stage.on('message:externalData', function(data) {
text.attr('text', data.nodeData);
});
stage.on('message', function(data) {
if (data.bonsai === 'tree') {
text.attr('textFillColor', 'red');
}
});
stage.sendMessage('ready', {});
}
}
);
// emitted before code gets executed
movie.on('load', function() {
// receive event from the runner context
movie.on('message:ready', function() {
// send a categorized message to the runner context
movie.sendMessage('externalData', {
nodeData: document.getElementById('movie').innerHTML
});
// send just a message to the runner context
movie.sendMessage({
bonsai: 'tree'
});
});
});
</script>
The fist question is: why the following code modification:
<script src="http://cdnjs.cloudflare.com/ajax/libs/bonsai/0.4/bonsai.min.js"></script>
<div id="movie"></div>
<script>
var movie = bonsai.run(document.getElementById('movie'), 'movie.js');
// emitted before code gets executed
movie.on('load', function() {
// receive event from the runner context
movie.on('message:ready', function() {
// send a categorized message to the runner context
movie.sendMessage('externalData', {
nodeData: document.getElementById('movie').innerHTML
});
// send just a message to the runner context
movie.sendMessage({
bonsai: 'tree'
});
});
});
</script>
where movie.js is:
document.getElementById('movie'),
{
code: function() {
// receive data from the other side
var text = new Text().addTo(stage);
stage.on('message:externalData', function(data) {
text.attr('text', data.nodeData);
});
stage.on('message', function(data) {
if (data.bonsai === 'tree') {
text.attr('textFillColor', 'red');
}
});
stage.sendMessage('ready', {});
}
}
throws “WORKER undefined”
Why original code does not work in IE9?
I am interested in using SignalR to provide a better user experience for some long-running processes in my application and have just created my first test SignalR project. I created an empty web project and then used NuGet to install the SignalR.Sample package. The StockTicker.html page example works perfectly. I then created my own Hub and test page.
using System.Threading;
using Microsoft.AspNet.SignalR.Hubs;
namespace SignalR.Test
{
[HubName("testHub")]
public class TestHub : Hub
{
public void LongRunningProcess()
{
Thread.Sleep(1000);
this.Clients.Caller.updateStatus("25% Completed");
Thread.Sleep(1000);
this.Clients.Caller.updateStatus("50% Completed");
Thread.Sleep(1000);
this.Clients.Caller.updateStatus("75% Completed");
Thread.Sleep(1000);
this.Clients.Caller.updateStatus("Done");
}
}
}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>SignalR - Long Running Process</title>
</head>
<body>
<h1>Long Running Process</h1>
<p>Status:</p>
<ul id="status">
<li>Loading hub...</li>
</ul>
<script src="/bundles/jquery"></script>
<script src="/Scripts/jquery.signalR-1.0.0-alpha2.js"></script>
<script src="/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
var hub = $.connection.testHub;
hub.updateStatus = function (message) {
$("#status").append("<li>" + message + "</li>");
};
$.connection.hub.start().done(function () {
$("#status").children().first().text("Hub loaded.");
hub.longRunningProcess();
})
.fail(function() {
$("#status").children().first().text("Hub failed");
});
})
</script>
</body>
</html>
When I run the page, I get the following (Firebug) error:
TypeError: hub.longRunningProcess is not a function
hub.longRunningProcess();
If I look in /signalr/hubs I see the following script towards the end of the file:
signalR.testHub = signalR.hub.createHubProxy('testHub');
signalR.testHub.client = { };
signalR.testHub.server = {
longRunningProcess: function () {
return signalR.testHub.invoke.apply(signalR.testHub, $.merge(["LongRunningProcess"], $.makeArray(arguments)));
}
};
Any advice/pointers on where I'm going wrong would be much appreciated.
I found the problem. The client script should looks as follows:
$(function () {
var hub = $.connection.testHub;
hub.client.updateStatus = function (message) {
$("#status").append("<li>" + message + "</li>");
};
$.connection.hub.start().done(function () {
$("#status").children().first().text("Hub loaded.");
hub.server.longRunningProcess();
})
.fail(function() {
$("#status").children().first().text("Hub failed");
});
})
Notice the addition of the .client and .server properties to the hub method declarations, e.g. hub.client.updateStatus() and hub.server.longRunningProcess()