SignalR – Push Data To Clients Using IHubContext
This article is a second contribution to the series dedicated to SignalR. My previous article focused on introduction and basics of SignalR.
Access to the Hubs from outside of the Hub class
The Clients dynamic property of the Hub gives you access to all clients connected to the hub within the hub class. However, what if you would like to push data to the clients from outside of the Hub class. One of the most common scenarios is when you want to push data to the clients from an admin system in your back-end.
This is where the static GlobalHost SignalR class comes to rescue. It gives you access to the HubContext through the IConnectionManager interface.
1var myHub = GlobalHost.ConnectionManager.GetHubContext<FeedHub>();
2var result = myHub.Clients.receiveData(yourData);
The IHubContext, which is returned from the GetHubContext exposes the dynamic Clients and IGroupManager Groups. This means that you can get access to the clients connected to the hubs from anywhere in your app. Pretty cool.
Extend our example to publish from controllers
Lets assume, we want to add functionality to our existing example to publish data from some sort of mangement/admin controller. All we need is a new hub (FeedHub), the management controller and a bit of Javascript to wire it all together.
Lets create the hub first. It is actually just a proxy between the JS client and the controller so it could be empty since all methods are called via the Clients dynamic variable.
1public class FeedHub : Hub
2{
3
4}
Then, we need a controller that will create and publish the items to the clients via the FeedHub.
1public class ManageController : Controller
2{
3 private readonly IRepository _repository;
4
5 public ManageController(IRepository repository)
6 {
7 _repository = repository;
8 }
9
10 public ActionResult Index()
11 {
12 var model = new ManageModel() {Items = _repository.FindAll<FeedItem>()};
13 return View(model);
14 }
15
16 public ActionResult Add()
17 {
18 var model = new AddFeedItemModel();
19 return View(model);
20 }
21
22 [HttpPost]
23 public ActionResult Add(AddFeedItemModel model)
24 {
25 var update = new FeedItem() {Message = model.Content};
26 _repository.Save(update);
27
28 return RedirectToAction("Index");
29 }
30
31 public ActionResult Publish(long feedItemId)
32 {
33 var myHub = GlobalHost.ConnectionManager.GetHubContext<FeedHub>();
34
35 var item = _repository.FindById<FeedItem>(feedItemId);
36 item.IsPublished = true;
37 _repository.Save(item);
38
39 var result = myHub.Clients.receive(item);
40 return RedirectToAction("Index");
41 }
42}
Finally, we need to wire-up the front-end with Javascript and template file to render the data coming from the server
1function Feed() {
2 var feedHub = undefined;
3
4 var init = function () {
5 feedHub = $.connection.feedHub;
6
7 feedHub.receive = function (item) {
8 var selector = "ul.feed-list li[data-id=" + item.Id + "]";
9 if (!($(selector).length > 0)) {
10 $("ul.feed-list").prepend($(".feed-template").render(item));
11 $("ul.feed-list li:gt(3)").remove();
12 }
13 };
14 };
15
16 init();
17};
18
19
20<script class="feed-template" type="text/x-jquery-tmpl">
21 <li data-id="{{>Id}}">
22 <div class="row-fluid">
23 <div class="span8">
24 <h3>{{>Message}}</h3>
25 </div>
26 </div>
27 </li>
28</script>
Simple as that – the static GlobalHost class gives you the full power to push data to clients via any existing hub. Any questions, ping me @mirajavora
You can download the entire sample using the link below. You should change the connection string in web.config and run /boot to generate the DB schema. Remember that the sample is intended as a showcase of what SignalR can do and deliberately breaks several patterns for simplicity.
Related Articles
SignalR – Introduction To SignalR SignalR – Publish Data Using IHubContext SignalR – Publish Data Using Proxies SignalR – Dependency Injection