Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

calling SignalR hub from WebAPI controller issues

Tags:

c#

signalr

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.

  1. I created a new project from the ASP.NET MVC WebAPI template.
  2. I added a new SignalR Hub to the project called ChatHub.
  3. Added a HTML page that on load, connects to ChatHub, joins to a group and sends a message to that group. This works great.
  4. HTML page also has a button that when clicked will fire an ajax call to the ValuesController's post method. In the ValuesController's post method, I want to broadcast a message to all the connected clients of the group. I cannot get this to work.

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

like image 641
DapperDanh Avatar asked May 22 '13 15:05

DapperDanh


People also ask

Can SignalR be used in Web API?

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.

Is SignalR two-way communication?

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.

Is SignalR asynchronous?

SignalR is an asynchronous signaling library for ASP.NET that our team is working on to help build real-time multi-user web application.


1 Answers

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;
like image 200
davidfowl Avatar answered Oct 07 '22 19:10

davidfowl