Reply back to exactly same client who connected and called with SignalR - asp.net-mvc

I am having a two tier application, with one being Windows Form application and other being Web Application with MVC.
Desktop Application has a SignalR Hub area which manages all client connected to it from Web App.
Hub Class
public delegate void ClientConnectionEventHandler(string clientId);
public delegate void ClientNameChangedEventHandler(string clientId, string newName);
public delegate void ClientInitializeEventHandler(string clientId);
public class StockTickerHub:Hub
{
static ConcurrentDictionary<string, string> _users = new ConcurrentDictionary<string, string>();
public static event ClientConnectionEventHandler ClientConnected;
public static event ClientConnectionEventHandler ClientDisconnected;
public static event ClientNameChangedEventHandler ClientNameChanged;
public static event ClientInitializeEventHandler ClientInitialized;
//Called when a client is connected
public override Task OnConnected()
{
_users.TryAdd(Context.ConnectionId, Context.ConnectionId);
ClientConnected?.Invoke(Context.ConnectionId);
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
string username;
_users.TryRemove(Context.ConnectionId, out username);
ClientDisconnected?.Invoke(Context.ConnectionId);
return base.OnDisconnected(stopCalled);
}
public void SetUserName(string userName)
{
_users[Context.ConnectionId] = userName;
ClientNameChanged?.Invoke(Context.ConnectionId, userName);
}
public void InitializeGrid()
{
ClientInitialized?.Invoke(Context.ConnectionId);
}
}
When web client connects to Desktop App, it's being added and connected.
Inherited Hub Class
public class ClientGateway
{
private BindingList<ClientItem> _clients = new BindingList<ClientItem>();
frmMasterTicker frm;
public ClientGateway()
{
//Register to hub events
StockTickerHub.ClientConnected += StockTickerHub_ClientConnected;
StockTickerHub.ClientNameChanged += StockTickerHub_ClientNameChanged;
StockTickerHub.ClientDisconnected += StockTickerHub_ClientDisconnected;
StockTickerHub.ClientInitialized += StockTickerHub_ClientInitialized;
}
private void StockTickerHub_ClientInitialized(string clientId)
{
InitializeGrid(clientId);
}
private void StockTickerHub_ClientDisconnected(string clientId)
{
var client = _clients.FirstOrDefault(x => x.Id == clientId);
if (client != null)
{
_clients.Remove(client);
}
}
private void StockTickerHub_ClientNameChanged(string clientId, string newName)
{
//Update client's name if it's available
var client = _clients.FirstOrDefault(x => x.Id == clientId);
if (client != null)
{
client.Name = newName;
SetOperationLogMessage.AddLogMessage(this.ToString(), "", $"Client name changed. Id:{clientId}, Name:{newName}");
SendTestMessage();
}
}
private void StockTickerHub_ClientConnected(string clientId)
{
//Add client to the list
_clients.Add(new ClientItem() { Id = clientId, Name = clientId });
SetOperationLogMessage.AddLogMessage("ClientGateway", "StockTickerHub_ClientConnected", $"Client connected:{clientId}");
}
public void SendTestMessage()
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>();
hubContext.Clients.All.addMessage("Ticker Server", "Hello handshake from server.");
}
public void InitializeGrid(string connectionid)
{
if (_clients.Count > 0)
{
frm = (frmMasterTicker)Helper.GetOpenForm("frmMasterTicker");
//string msg = "Hello from server at " + DateTime.Now.ToString();
string msg = JsonConvert.SerializeObject(frm.GetInitializeDataFromGrid());
var hubContext = GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>();
hubContext.Clients.Client(connectionid).initializeGrid(msg);
}
}
public void SendTickerData(object lstStock)
{
if (_clients.Count > 0)
{
//string msg = "Hello from server at " + DateTime.Now.ToString();
string msg = JsonConvert.SerializeObject(lstStock);
var hubContext = GlobalHost.ConnectionManager.GetHubContext<StockTickerHub>();
hubContext.Clients.Client("").getTickerData(msg);
}
}
}
Web Page Code
//Connect to SignalR server and get the proxy
function connect() {
$.connection.hub.url = url;
simpleHubProxy = $.connection.stockTickerHub;
if (simpleHubProxy) {
$.connection.hub.start().done(function () {
writeToLog("Connected...");
simpleHubProxy.server.setUserName("RMSAdmin");
RequestGridInitialData();
})
.fail(function () {
alert("Can't connect");
})
;
simpleHubProxy.client.addMessage = function (name, message) {
writeToLog(name + ":" + message);
}
simpleHubProxy.client.initializeGrid = function (message) {
dtSource = JSON.parse(message);
$("#grid").data("kendoGrid").dataSource.data(dtSource);
}
simpleHubProxy.client.getTickerData = function (message) {
writeToLog(message);
}
$.connection.hub.disconnected(function () {
writeToLog("Server disconnected.");
});
$.connection.hub.reconnecting(function () {
writeToLog("Server reconnecting...");
});
$.connection.hub.reconnected(function () {
writeToLog("Server reconnected...");
});
$.connection.hub.error(function (error) {
console.log('SignalR error: ' + error)
});
}
}
connect();
I can get the connection id from Hub.
Now I have a Windows Form. In which, I want to send data to exactly the same client who connected recently. I have a list of all clients connection with id. But within that, who connected recently and to whom I need to send data from Form, I am unable to do the progress with.
Following is a code try inside a Windows Form, which works, but it sends data to all connected client.
hubContext.Clients.All.getTickerData(JsonConvert.SerializeObject(tmpStock));
I want to send data only to that client who connects recently. How should I do that?

In the piece of code where you are sending the windows form data, you can call:
hubContext.Clients.Caller.getTickerData(JsonConvert.SerializeObject(tmpStock));
The .Caller will send the message to the client that invoked the method.
You can read more about it, in the oficial microsoft documentation, here: https://learn.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-server#selectingclients
Edit: Since you don't have access to the .Caller method outside the hub you need to save the ClientId inside the hub and pass it the the outside class... SO there you will be able to call the caller client by id:
hubContext.Clients.Client(clientId).getTickerData(JsonConvert.SerializeObject(tmpStock));

Related

Passing parameters to a SignalR Hub (ASP NET Core 6)

how can i pass parameters to a asynchronous task of a SignalR Hub?
The paramaeters id, dis and dg have to be passes to the asynchronous task SendResults().
My hub:
public class ResultHub : Hub
{
ResultRepository ResultRepository;
public ResultHub(IConfiguration configuration)
{
var connectionString = configuration.GetConnectionString("DefaultConnection");
ResultRepository = new ResultRepository(connectionString);
}
public async Task SendResults()
{
int id = 2977;
int dis = 3;
int dg = 1;
var Results = ResultRepository.GetResults(id, dis, dg);
await Clients.All.SendAsync("ReceivedResults", Results);
}
}
The asynchronous task SendResults gets the results with ResultRepository.GetResults.
SendResults is called in the Javascript within the chtml file:
function InvokeResults() {
connection.invoke("SendResults").catch(function (err) {
return console.error(err.toString());
});
}
and in the method TableDependency_OnChanged of the class SubscribeResultTableDependency
public class SubscribeResultTableDependency : ISubscribeTableDependency
{
SqlTableDependency<Result> tableDependency;
ResultHub ResultHub;
public SubscribeResultTableDependency(ResultHub resultHub)
{
this.resultHub = resultHub;
}
public void SubscribeTableDependency(string connectionString)
{
tableDependency = new SqlTableDependency<Result>(connectionString);
tableDependency.OnChanged += TableDependency_OnChanged;
tableDependency.OnError += TableDependency_OnError;
tableDependency.Start();
}
private void TableDependency_OnChanged(object sender, TableDependency.SqlClient.Base.EventArgs.RecordChangedEventArgs<Result> e)
{
if (e.ChangeType != TableDependency.SqlClient.Base.Enums.ChangeType.None)
{
resultHub.SendResults();
}
}
private void TableDependency_OnError(object sender, TableDependency.SqlClient.Base.EventArgs.ErrorEventArgs e)
{
Console.WriteLine($"{nameof(Result)} SqlTableDependency error: {e.Error.Message}");
}
}
Passing of parameters in the connection.invoke of the Javascript works, but how can this be done in both calls?
(Microsoft.NETCore.App\6.0.13)
According to your description, if you want to how to pass the parameter from the js to the Hub method, I suggest you could refer to below example:
1.Modify the hub method to add parameter, like below:
public class ChatHub : Hub
{
public async Task SendResults(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
2.Modify the js to add the parameter:
connection.invoke("SendResults", "parameter1", "parameter2").catch(function (err) {
return console.error(err.toString());
});

ASP.NET MVC SignalR Client methods not invoked in separate project

I have to two separate asp.net projects on the same server. All correct SignalR nuget packages are installed as far as I know on both projects. One is the ChatServer and another is a ChatClient. Both are DotNetNuke projects.
The second project DOES know about signalR because OnConnected in Server project gets triggered when running client project and the client user is inserted as online (through the server OnConnected method).
When the sever comes online (by launching server project)the method in the client "getonlineusers" does not get triggered though.
But if I refresh the client, the server does show as offline. But I shouldnt have to refresh.
I am probably missing something not sure if I am creating a proxy correctly for the client project, any help would be greatly appreciated.
How do you connect a client separate project to the project that has the hub with SignalR?
In the ChatServer project:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
public class ChatSupportHub : Hub
{
private ChatServerManager CSM { get; set; }
private int UserID { get; set; }
//private UserInfo CurrentUser { get; set; }
public ChatSupportHub()
{
CSM = new ChatServerManager();
//CurrentUser = DotNetNuke.Entities.Users.UserController.Instance.GetCurrentUserInfo();
}
public override Task OnConnected()
{
int outNumber = -1;
Online user = new Online();
User dbUser = new User();
var userid = Context.QueryString["userid"];
bool success = Int32.TryParse(userid, out outNumber);
string connID = Context.ConnectionId;
if (success)
{
user.ID = outNumber;
dbUser = CSM.GetUser(outNumber);
UserID = outNumber;
}
user.ConnectionID = connID;
user.Type = dbUser.TypeID.HasValue ? CSM.GetUserType((int) dbUser.TypeID) : null;
user.ShowOnline = true;
CSM.AddOnlineUser(user);
var onlineUsers = CSM.GetOnlineUsers();
var clients = Clients.Caller;
string onlineUserJSON = JsonConvert.SerializeObject(onlineUsers);
clients.getonlineusers(dbUser.Name, onlineUserJSON);
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
var username = Context.User.Identity.Name;
int userID = CSM.GetUserId(username);
CSM.RemoveOnlineUser(userID);
return base.OnDisconnected(stopCalled);
}
}
And the View index page of the ChatServer project:
<script src="~/myServertProjectPath/Scripts/jquery.signalR-2.4.1.min.js"></script>
<script src="~/signalr/hubs"></script>
<script>
$(function () {
// set up the hub connection
var hub = $.connection.chatSupportHub;
$.connection.hub.qs = "userid=" + #Model.CurrentUserInfo.UserID.ToString();
hub.client.getonlineusers = function (currentUsername, onlineUsers) {
if (onlineUsers) {
console.log('There are users online and one is: ' + currentUsername);
}
}
$.connection.hub
.start()
.done(function () {
})
});
And same thing in the separate client project for the view:
<script src="~/myClientProjectPath/Scripts/jquery.signalR-2.4.1.min.js"></script>
<script src="~/signalr/hubs"></script>
<script>
$(function () {
connect();
});
function connect() {
hub = $.connection.chatSupportHub;
$.connection.hub.qs = "userid=" + #Model.CurrentUserInfo.UserID.ToString();
hub.client.getonlineusers = function (currentUsername, onlineUsers) {
if (onlineUsers) {
console.log ("Hello from the separate project.");
}
}
$.connection.hub
.start()
.done(function () {
})
}
</script>

Asp.net SignalR not working while deployed in Azure

I am using Asp.Net signal for sending user specific notification. Everything working fine in debug mode using visual studio but the same breaks while deployed to Azure.
I am using redis cache.
Startup.cs
using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(NotifSystem.Web.Startup))]
namespace NotifSystem.Web
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
GlobalHost.DependencyResolver.UseStackExchangeRedis(new RedisScaleoutConfiguration("mySrver:6380,password=password,ssl=True", "YourServer"));
app.MapSignalR();
}
}
}
My Hub Class:
using Microsoft.AspNet.SignalR;
using NotificationHub.Models.Hubs;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace NotificationHub.Hubs
{
public class NotificationHub : Hub
{
private static readonly ConcurrentDictionary<string, UserHubModels> Users =
new ConcurrentDictionary<string, UserHubModels>(StringComparer.InvariantCultureIgnoreCase);
//private NotifEntities context = new NotifEntities();
//Logged Use Call
public void GetNotification()
{
try
{
string loggedUser = Context.User.Identity.Name;
//Get TotalNotification
//string totalNotif = LoadNotifData(loggedUser);
//Send To
UserHubModels receiver;
if (Users.TryGetValue(loggedUser, out receiver))
{
var cid = receiver.ConnectionIds.FirstOrDefault();
var context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
context.Clients.Client(cid).broadcaastNotif();
}
}
catch (Exception ex)
{
ex.ToString();
}
}
//Specific User Call
public void SendNotification(string SentTo,string Notification)
{
try
{
//Get TotalNotification
//string totalNotif = LoadNotifData(SentTo);
//Send To
UserHubModels receiver;
if (Users.TryGetValue(SentTo, out receiver))
{
var cid = receiver.ConnectionIds.FirstOrDefault();
var context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
context.Clients.Client(cid).broadcaastNotif(Notification);
}
}
catch (Exception ex)
{
ex.ToString();
}
}
private string LoadNotifData(string userId)
{
return userId;
int total = 0;
//var query = (from t in context.Notifications
// where t.SentTo == userId
// select t)
// .ToList();
total = 6;
return total.ToString();
}
public override Task OnConnected()
{
string userName = Context.User.Identity.Name;
string connectionId = Context.ConnectionId;
var user = Users.GetOrAdd(userName, _ => new UserHubModels
{
UserName = userName,
ConnectionIds = new HashSet<string>()
});
lock (user.ConnectionIds)
{
user.ConnectionIds.Add(connectionId);
if (user.ConnectionIds.Count == 1)
{
Clients.Others.userConnected(userName);
}
}
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
string userName = Context.User.Identity.Name;
string connectionId = Context.ConnectionId;
UserHubModels user;
Users.TryGetValue(userName, out user);
if (user != null)
{
lock (user.ConnectionIds)
{
user.ConnectionIds.RemoveWhere(cid => cid.Equals(connectionId));
if (!user.ConnectionIds.Any())
{
UserHubModels removedUser;
Users.TryRemove(userName, out removedUser);
Clients.Others.userDisconnected(userName);
}
}
}
return base.OnDisconnected(stopCalled);
}
}
}
Javascript Code:
var hub = $.connection.notificationHub;
hub.client.broadcaastNotif = function (notification) {
setTotalNotification(notification)
};
$.connection.hub.start()
.done(function () {
console.log("Connected!");
hub.server.getNotification();
})
.fail(function () {
console.log("Could not Connect!");
});
});
function setTotalNotification(notification) {
if (notification) {
GetUnreadNotificationCount();
$('#m_topbar_notification_icon .m-nav__link-icon').addClass('m-animate-shake');
$('#m_topbar_notification_icon .m-nav__link-badge').addClass('m-animate-blink');
}
else {
$('#m_topbar_notification_icon .m-nav__link-icon').removeClass('m-animate-shake');
$('#m_topbar_notification_icon .m-nav__link-badge').removeClass('m-animate-blink');
}
}
I have enabled Websocket for that particular App Service.
Cross user notification sending is not successful it only works if the logged in user sends notification to himself only.
Update:
I checked that while a logged in user is doing an activity so that the notification goes to that particular user then it works. Like if a user user1 sends a notification to user1 then there is no issue.
We had same problem with our Azure SignalR redis BackPlane POC.
But We tried redis with No SSL port then the Azure SignalR redis BackPlane started working fine. Please check the screenshot Below. Now since the enviorment is self contained we do not need it even HTTPS. We are managing it by Resource Groups and Port Whitelisting.

How to live notification in MVC with SignalR?

I'm trying to make live notification using signalR. My project is running on localhost. But I don't see my notification when I set webconfig server-side. (although I did it with signalR)
When I run the 'internet' part of Chrome 's check item, I see that the request does not fall. how do I make this problem?
ajax code;
function updateNotification() {
$('#notiContent').empty();
$('#notiContent').append($('<li>Yükleniyor...</li>'));
$.ajax({
type: 'GET',
datatype : JSON,
contentType: 'application/json; charset=utf-8',
url: '/notification/GetNotificationFlows',
success: function (response) {
$('#notiContent').empty();
if (response.length == 0) {
$('#notiContent').append($('<li>Data yok..</li>'));
}
$.each(response, function (index, value) {
$('#notiContent').append($('<li>Yeni kişi : ' + value.flowName + ' (' + value.flowPhone + ') eklendi.</li>'));
});
},
error: function (error) {
console.log(error);
}
})
}
Global.asax;
string con = ConfigurationManager.ConnectionStrings["sqlConString"].ConnectionString;
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
SqlDependency.Start(con);
}
protected void Session_Start(object sender, EventArgs e)
{
NotificationComponent NC = new NotificationComponent();
var currentTime = DateTime.Now;
HttpContext.Current.Session["LastUpdated"] = currentTime;
NC.RegisterNotification(currentTime);
}
protected void Application_End()
{
//here we will stop Sql Dependency
SqlDependency.Stop(con);
}
}
Notification component
public void RegisterNotification(DateTime currentTime)
{
string conStr = ConfigurationManager.ConnectionStrings["sqlConString"].ConnectionString;
string sqlCommand = #"SELECT [flowId],[flowName],[flowEMail],[flowPhone],[kaynakId] from [dbo].[flow] where [createDate] > #createDate";
//you can notice here I have added table name like this [dbo].[Contacts] with [dbo], its mendatory when you use Sql Dependency
using (SqlConnection con = new SqlConnection(conStr))
{
SqlCommand cmd = new SqlCommand(sqlCommand, con);
cmd.Parameters.AddWithValue("#createDate", currentTime);
if (con.State != System.Data.ConnectionState.Open)
{
con.Open();
}
cmd.Notification = null;
SqlDependency sqlDep = new SqlDependency(cmd);
sqlDep.OnChange += sqlDep_OnChange;
//we must have to execute the command here
using (SqlDataReader reader = cmd.ExecuteReader())
{
// nothing need to add here now
}
}
}
void sqlDep_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
SqlDependency sqlDep = sender as SqlDependency;
sqlDep.OnChange -= sqlDep_OnChange;
//from here we will send notification message to client
var notificationHub = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
notificationHub.Clients.All.notify("eklendi.");
//re-register notification
RegisterNotification(DateTime.Now);
}
}
public List<flow> GetFlows(DateTime afterDate)
{
using (smartCMSEntities dc = new smartCMSEntities())
{
return dc.flow.Where(a => a.createDate > afterDate).OrderByDescending(a => a.createDate).ToList();
}
}
Notification Controller
public JsonResult GetNotificationFlows()
{
var notificationRegisterTime = Session["LastUpdated"] != null ? Convert.ToDateTime(Session["LastUpdated"]) : DateTime.Now;
NotificationComponent NC = new NotificationComponent();
var list = NC.GetFlows(notificationRegisterTime);
Session["LastUpdate"] = DateTime.Now;
return new JsonResult { Data = list, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
Notification Hub
public class NotificationHub : Hub
{
//public void Hello()
//{
// Clients.All.hello();
//}
}
SQL (for sql dependency)
ALTER DATABASE [db_name] SET ENABLE_BROKER with rollback immediate;
I had the same problem you need to create your function inside your Hub.
Let say
public class NotificationHub : Hub
{
public static void Send()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
context.Clients.All.displayStatus();
}
}
And call it in your html
function updateNotificationCount() {
$('span.count').show();
var count = 0;
count = parseInt($('span.count').html()) || 0;
count++;
$('span.noti').css("color", "white");
// $('span.count').css({ "background-color": "red", "color": "white" });
$('span.count').html(count);
}
// signalr js code for start hub and send receive notification
var hub = $.connection.notificationHub;
// Declare a function on the hub hub so the server can invoke it
hub.client.displayStatus = function () {
updateNotificationCount();
};
// Start the connection
$.connection.hub.start();

Calling a Client Method on a Windows Service

I have a SignalR client in a Windows Service that successfully calls a Server method in an MVC app. First the Server Code:
public class AlphaHub : Hub
{
public void Hello(string message)
{
// We got the string from the Windows Service
// using SignalR. Now need to send to the clients
Clients.All.addNewMessageToPage(message);
// Send message to Windows Service
}
and
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
app.MapSignalR("/signalr", new HubConfiguration());
}
}
The Windows Service client is:
protected override async void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart");
try
{
var hubConnection = new HubConnection("http://localhost.com/signalr", useDefaultUrl: false);
IHubProxy alphaProxy = hubConnection.CreateHubProxy("AlphaHub");
await hubConnection.Start();
await alphaProxy.Invoke("Hello", "Message from Service");
}
catch (Exception ex)
{
eventLog1.WriteEntry(ex.Message);
}
}
It sends a message to the MVC Server. Now I want to call the other way from server to client. The Client Programming Guide has the following code examples which will NOT work as this is not a desktop.
WinRT Client code for method called from server without parameters (see WPF and Silverlight examples later in this topic)
var hubConnection = new HubConnection("http://www.contoso.com/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub");
stockTickerHub.On("notify", () =>
// Context is a reference to SynchronizationContext.Current
Context.Post(delegate
{
textBox.Text += "Notified!\n";
}, null)
);
await hubConnection.Start();
How can I call a method on the client?
The .NET client side code seems fine. You can simply get rid of Context.Post since your client is running inside of a Windows Service and doesn't need a SyncContext:
protected override async void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart");
try
{
var hubConnection = new HubConnection("http://localhost.com/signalr", useDefaultUrl: false);
IHubProxy alphaProxy = hubConnection.CreateHubProxy("AlphaHub");
stockTickerHub.On("Notify", () => eventLog1.WriteEntry("Notified!"));
await hubConnection.Start();
await alphaProxy.Invoke("Hello", "Message from Service");
}
catch (Exception ex)
{
eventLog1.WriteEntry(ex.Message);
}
}
You can invoke the "Notify" callback from inside your AlphaHub on the server like so:
public class AlphaHub : Hub
{
public void Hello(string message)
{
// We got the string from the Windows Service
// using SignalR. Now need to send to the clients
Clients.All.addNewMessageToPage(message);
// Send message to the Windows Service
Clients.All.Notify();
}
Any client will be able to listen to these notifications since we are using Clients.All. If you want to avoid this, you need some way to authenticate your Windows Service and get its ConnectionId. Once you have that, you can send to the Windows Service specifically like so:
Clients.Client(serviceConnectionId).Notify();
Hope this helps.
Windows Service with self hosted SignalR
public partial class MyWindowsService : ServiceBase
{
IDisposable SignalR { get; set; }
public class SignalRStartup
{
public static IAppBuilder App = null;
public void Configuration(IAppBuilder app)
{
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration()
{
// EnableDetailedErrors = true
};
map.RunSignalR(hubConfiguration);
});
}
}
public MyWindowsService()
{
InitializeComponent();
}
protected override void OnStart(string[] args) { Start(); }
protected override void OnStop() { Stop(); }
public void Start()
{
SignalR = WebApp.Start<SignalRStartup>("http://localhost:8085/signalr");
CallToMvcJavascript();
}
public new void Stop()
{
SignalR.Dispose();
}
private void CallToMvcJavascript(){
GlobalHost.ConnectionManager.GetHubContext<MyHub>().Clients.All.addNotice(// object/data to send//);
}
}
The Hub in the Windows Service
public class MyHub : Hub
{
public void Send()
{
Clients.All.confirmSend("The service received the client message");
}
}
The Javascript
$.connection.hub.logging = true;
$.connection.hub.url = "http://localhost:8085/signalr";
var notices = $.connection.myHub;
notices.client.addNotice = function(notice) {
console.log(notice);
};
notices.client.confirmSend = function(msg) {
alert(msg);
};
$.connection.hub.start().done(function() {
$('#myTestBtn').on('click', function() {
notices.server.send();
});
});

Resources