ASP.NET MVC SignalR Client methods not invoked in separate project - asp.net-mvc

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>

Related

Reply back to exactly same client who connected and called with SignalR

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));

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 prevent an ASP NET MVC application requesting authorization from Google every hour?

We are using packages Google.Apis.Calendar.v3 and Google.Apis.Auth.Mvc in an ASP .NET MVC application with users.
We want each user to have access to their Google Calendar, so it is necessary that each one of them give permission to our application. We have read a lot and it is said that there is a way to prevent the application from asking the user for these credentials every hour
We have looked at solutions like this and do not work for us
solutions like this one we do not know how to use them in our MVC application
users may or may not register on our site using google
This is the last code that we tried and everything works correctly, except that every hour the users who had already given permission to our application had to do it again and to re-authenticate with google and give permissions:
FlowMetadata implementation
public class AppFlowMetadata : FlowMetadata
{
private static readonly IAuthorizationCodeFlow flow =
new ForceOfflineGoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets
{
ClientId = "MY_VALID_CLIENT_ID",
ClientSecret = "MY_VALID_CLIENT_SECRET"
},
Scopes = new[] { CalendarService.Scope.Calendar },
DataStore = new FileDataStore("Google.Api.Auth.Store")
});
public override string GetUserId(Controller controller)
{
var userId = controller.User.Identity.GetUserId();
return userId;
}
public override IAuthorizationCodeFlow Flow
{
get { return flow; }
}
}
GoogleAuthorizationCodeFlow implementation forcing offline
internal class ForceOfflineGoogleAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
{
public ForceOfflineGoogleAuthorizationCodeFlow(GoogleAuthorizationCodeFlow.Initializer initializer) : base(initializer) { }
public override AuthorizationCodeRequestUrl CreateAuthorizationCodeRequest(string redirectUri)
{
return new GoogleAuthorizationCodeRequestUrl(new Uri(AuthorizationServerUrl))
{
ClientId = ClientSecrets.ClientId,
Scope = string.Join(" ", Scopes),
RedirectUri = redirectUri,
AccessType = "offline",
ApprovalPrompt = "force"
};
}
}
AuthCallbackController
public class AuthCallbackController : Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController
{
protected override Google.Apis.Auth.OAuth2.Mvc.FlowMetadata FlowData
{
get { return new AppFlowMetadata(); }
}
}
Test controller action
public async Task IndexAsync(CancellationToken cancellationToken)
{
var result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()).
AuthorizeAsync(cancellationToken);
if (result.Credential != null)
{
var service = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = result.Credential,
ApplicationName = "TEST",
});
IList list = service.CalendarList.List().Execute().Items;
var selected = list.First();
EventsResource.ListRequest request = service.Events.List(selected.Id);
request.TimeMin = new DateTime?(new DateTime(2017, 1, 1));
request.ShowDeleted = false;
request.SingleEvents = true;
request.MaxResults = 10;
request.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime;
Events events = request.Execute();
return View(events);
}
else
{
return new RedirectResult(result.RedirectUri);
}
}

mvc signalr how to display all connected users

I need to build a chat using signalr and I am new in this.
So far I got only the chat by reading some others codes and tutorials and this is what I got:
on my ChatApp.Hubs I got the following code
public static class UserHandler
{
public static HashSet<string> ConnectedIds = new HashSet<string>();
}
public class ChatHub : Hub
{
public void Send(string name, string message)
{
// Call the addNewMessageToPage method to update clients.
Clients.All.addNewMessageToPage(name, message);
}
public override Task OnConnected()
{
UserHandler.ConnectedIds.Add(Context.ConnectionId);
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
UserHandler.ConnectedIds.Remove(Context.ConnectionId);
return base.OnDisconnected(stopCalled);
}
}
and my view I copy past from a tutorial
#{
ViewBag.Title = "Chat";
}
<h2>Chat</h2>
<div class="container">
<input type="text" id="message" />
<input type="button" id="sendmessage" value="Send" />
<input type="hidden" id="displayname" />
<ul id="discussion">
</ul>
</div>
#section scripts {
<!--Script references. -->
<!--The jQuery library is required and is referenced by default in _Layout.cshtml. -->
<!--Reference the SignalR library. -->
<script src="~/Scripts/jquery.signalR-2.1.0.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="~/signalr/hubs"></script>
<!--SignalR script to update the chat page and send messages.-->
<script>
$(function () {
// Reference the auto-generated proxy for the hub.
var chat = $.connection.chatHub;
// Create a function that the hub can call back to display messages.
chat.client.addNewMessageToPage = function (name, message) {
// Add the message to the page.
$('#discussion').append('<li><strong>' + htmlEncode(name)
+ '</strong>: ' + htmlEncode(message) + '</li>');
};
// Get the user name and store it to prepend to messages.
$('#displayname').val(prompt('Enter your name:', ''));
// Set initial focus to message input box.
$('#message').focus();
// Start the connection.
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
// Call the Send method on the hub.
chat.server.send($('#displayname').val(), $('#message').val());
// Clear text box and reset focus for next comment.
$('#message').val('').focus();
});
});
});
// This optional function html-encodes messages for display in the page.
function htmlEncode(value) {
var encodedValue = $('<div />').text(value).html();
return encodedValue;
}
</script>
}
what I need now is to display all the connected users in the view
Appriciate your help
Thanks in advance
So, you pretty much either want to just store all 'Active' connections in some kind of database/storage or a static hashset/dictionary.
You save the ConnectionIds when the user connects and remove them when they disconnect :
Hub
public class ChatHub : Hub
{
static HashSet<string> CurrentConnections = new HashSet<string>();
public override Task OnConnected()
{
var id = Context.ConnectionId;
CurrentConnections.Add(id);
return base.OnConnected();
}
public override System.Threading.Tasks.Task OnDisconnected()
{
var connection = CurrentConnections.FirstOrDefault(x => x == Context.ConnectionId);
if (connection != null)
{
CurrentConnections.Remove(connection);
}
return base.OnDisconnected();
}
//return list of all active connections
public List<string> GetAllActiveConnections()
{
return CurrentConnections.ToList();
}
}
Client
I added a button and an unordered list.
HTML
<button id="show-all-connections">Show Connections</button>
<ul id="user-list">
</ul>
And added this javascript (using jQuery)
$("#show-all-connections").on("click", function () {
debugger;
chatHub.server.getAllActiveConnections().done(function (connections) {
$.map(connections, function (item) {
$("#user-list").append("<li>Connection ID : " + item + "</li>");
});
});
});
Hope this helps.
Update
In your scenario, I don't see any hooks into using a custom UserId Provider or anything, so you're going to have to ask the User for a User Name and save the Connection ID with that.
HTML
JavaScript
$("#add-connection").click(function () {
var name = $("#user-name").val();
if (name.length > 0) {
chatHub.server.connect(name);
}
else {
alert("Please enter your user name");
}
});
Hub
static List<Users> SignalRUsers = new List<Users>();
public void Connect(string userName)
{
var id = Context.ConnectionId;
if (SignalRUsers .Count(x => x.ConnectionId == id) == 0)
{
SignalRUsers .Add(new Users{ ConnectionId = id, UserName = userName });
}
}
public override System.Threading.Tasks.Task OnDisconnected()
{
var item = SignalRUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);
if (item != null)
{
SignalRUsers.Remove(item);
}
return base.OnDisconnected();
}
Users.cs
public class Users
{
public string ConnectionId { get; set; }
public string UserName { get; set; }
}
This is psuedo code since I am not able to run this code at the moment. Hope it helps and gives you a clear enough direction.

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