2013-05-22 85 views
7

我无法弄清楚如何从WebAPI ApiController调用SignalR集线器。我已经组建了一个示例,您可以下载here来简化问题并演示此问题。从WebAPI控制器问题调用SignalR集线器

  1. 我从ASP.NET MVC WebAPI模板创建了一个新项目。
  2. 我在项目中添加了一个名为ChatHub的新SignalR Hub。
  3. 添加了一个加载的HTML页面,连接到ChatHub,加入到一个组中,并向该组发送消息。这很好。
  4. HTML页面还有一个按钮,点击后会触发ajax调用ValuesController的post方法。在ValuesController的post方法中,我想向组中所有连接的客户端广播一条消息。我无法得到这个工作。

我有一个简单的SignalR集线器,只有2种方法。

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

我创建了一个非常简单的HTML页面,它在DOM准备就绪时连接到Chat hub,如下所示。

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

没什么特别的。只要连接的集线器收到新消息,就会将新项目添加到无序列表中。有一个按钮可以将Ajax调用放入ValuesController后处理方法中。

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

集线器呼叫不起作用。不会抛出错误,但从未接收到该消息。在Hub的“Send”方法中放置断点也不起作用。我觉得我做对了。任何人帮助?同样,源代码可以发现here

回答

14

您所呼叫的客户端上的不同的方法:

API控制器

hubContext.Clients.Group("TestGroup").send("TestGroup", "Called from Controller"); 

枢纽

Clients.Group(room).newMessage(msg); 

要调用的方法是NewMessage作为不发送

chat.client.newMessage = onNewMessage; 
+0

大卫,非常感谢。所以它出现在服务器上,我可以调用HubContext.Clients.Group(“TestGroup”)的任何方法,比如hubContext.Clients.Group(“TestGroup”)。helloNasty,客户端将自动地响应相同的编制方法。疯。我需要研究C#动态功能:-) – DapperDanh

+0

这就是要点:) – davidfowl

+0

@dfowler:有没有什么办法可以从ApiController调用实际的ChatHub.Send方法?上面这种做法似乎是绕过ChatHub,直接转到Hub上下文来完成ChatHub.Send的功能 - 但ChatHub.Send中的任何其他功能都不会运行。这需要在ApiController?也许我只是在这里错过了一些东西。 – mutex