I cannot figure out how I can call into a SignalR hub from a WebAPI ApiController. I have put together a sample you can download here that simplifies the problem and demonstrates the issue.
I have a simple SignalR hub with just 2 methods.
[HubName("chat")]
public class ChatHub : Hub
{
public void Join(string room)
{
// NOTE: this is not persisted - ....
Groups.Add(Context.ConnectionId, room);
}
public void Send(string room, string message)
{
var msg = String.Format(
"{0}: {1}", Context.ConnectionId, message);
Clients.Group(room).newMessage(msg);
}
}
I created a very simple HTML page that connects to the Chat hub when the DOM is ready as shown here.
<html>
<head>
<title>Simple Chat</title>
<script src="Scripts/jquery-1.8.2.js" type="text/javascript"></script>
<script src="Scripts/jquery.signalR-1.0.0.js"></script>
<script src="signalr/hubs"></script>
<script type="text/javascript">
var chat;
//$(function () {
// connectToHubs();
//});
$(connectToHubs);
function connectToHubs() {
$.connection.hub.logging = true;
chat = $.connection.chat;
chat.client.newMessage = onNewMessage;
$.connection.hub.start({ transport: 'longPolling' }).done(function () {
chat.server.join("TestGroup").done(function () {
chat.server.send("TestGroup", "message from html");
});
});
$('#controller').click(postProficiencyUserAction);
}
var postProficiencyUserAction = function () {
//var token = $('[name=__RequestVerificationToken]').val();
var headers = {};
//headers["__RequestVerificationToken"] = token;
//var userAction = { createdOn: "2013-05-21T00:00:00", userId: "12345678-1234-1234-1234-000000000001", actionId: "12345678-1234-1234-1234-000000000003" };
$.ajax({
type: 'POST',
url: 'http://localhost:58755/api/values',
cache: false,
headers: headers,
contentType: 'application/json; charset=utf-8',
data: 'test',
dataType: "json",
success: function () {
},
error: function () {
}
});
};
function onNewMessage(message) {
// ... todo: validation !!!! :)
$('#messages').append('<li>' + message + '</li>');
};
</script>
</head>
<body>
<div>
<h2>Chat</h2>
<input type="button" id="controller" value="Controller Method" />
<div>
<h2>Message(s) Received</h2>
<ul id="messages"></ul>
</div>
</div>
</body>
</html>
Nothing fancy. Whenever the connected hub receives a new message, a new item is added to the unordered list. There is a button that makes an Ajax call into the ValuesController post method.
public class ValuesController : ApiController
{
// POST api/values
public void Post([FromBody]string value)
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ChatHub>();
hubContext.Clients.Group("TestGroup").send("TestGroup", "Called from Controller");
}
The Hub call does not work. An error is not thrown, but, the message is never received. Putting a breakpoint in the "Send" method of the Hub does not work either. I feel like I am doing it right. Anyone help? Again, source code can be found here
SignalR can be used together with Web API just fine, so some functionality in application which is not realtime and doesn't require persistent connection could be served by Web API.
There is a library called SignalR, which is included in ASP.NET Core. SignalR doesn't only enable you to achieve real-time two-way communication between applications. It also substantially simplifies the process of enabling all of this in the code.
SignalR is an asynchronous signaling library for ASP.NET that our team is working on to help build real-time multi-user web application.
You are calling different methods on the client:
API controller
hubContext.Clients.Group("TestGroup").send("TestGroup", "Called from Controller");
Hub
Clients.Group(room).newMessage(msg);
The method you want to call is newMessage not send
chat.client.newMessage = onNewMessage;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With