nov 18, 2013

Orchard + SignalR + Knockout.Js Real-time application

Translations:

In this article we will see how to create Real-time features in Orchard CMS using SignalR and Knockout.Js.

SignalR will take care about async calls between client side html and the server while Knockout.js will generate dinamically html tags based on JSON results.

Strong points of this approach:

- Async operations not blocking user between request and response in classic full page post.
- Only JSON data to transfer.
- Possibility to generate PUSH notifications to all connected users or groups of them.

We are going to create a simple button that once pressed will retrieve a list of contents from the database.

Let's start creating a new module:

codegen module testSignalR /includeinsolution:true

We need to install Proligence SignalR that contains SignalR references.

Download Knockout.Js and put js files in script folder inside your module.

Add a new folder Hubs and inside create a TestHub class like this: 

  public class TestHub : Hub {
        private readonly IOrchardServices _services;

        public TestHub(IOrchardServices services) {
            _services = services;
        }

        public void Test() {

            IEnumerable<dynamic> list = _services.ContentManager.Query().ForType("Articolo").List();

            var retList = list.Select(item => new {Id = item.Id, Title = item.TitlePart.Title});

            Clients.Caller.testNotify(retList);
        }
    } 

I've created an example Test() method that returns dummy data and convert it in a simple Id-Title list. List is passed by SignalR at client-side function testNotify in this way:

Clients.Caller.testNotify(retList);

Adding view:

@{ 
    Script.Require("jQuery_SignalR_Hubs").AtHead();
    
    Script.Include("knockout-3.0.0.js").AtHead();
}

@using (Script.Head())
{
    <script>
        $(function () {
            "use strict";

            function contentsViweModel() {

                var self = this;

                self.hub = $.connection.testHub;
                
                self.contents = ko.observableArray();
                
                self.test = function() {
                    self.hub.server.test();
                };
                
                self.hub.client.testNotify = function (contents) {
                    self.contents(contents);
                };
                
                self.clear = function () {
                    self.contents(null);
                };
            };

            var vm = new contentsViweModel();
            ko.applyBindings(vm);
            
            $.connection.hub.start();
        });
    </script>
}
    <div class="page-header">
        <h1>Real time test</h1>
        <h3>Using Knockout.Js and SignalR</h3>
    </div>

<button id="btnTest"  data-bind='click: $root.test'>@T("Test")</button>
<button id="btnTestClear"  data-bind='click: $root.clear'>@T("Clear")</button>

<fieldset class="contentItems bulk-items">
    <ul data-bind ="foreach: contents">
        <li>
            <div class="summary">
                <div class="properties">
                    <h3 data-bind="text: Title"></h3>
                </div>
            </div>
        </li>
    </ul>
</fieldset>

Client function testNotify(contents) is called from server and sets a contents object with JSON data. This object is defined as observableArray and Knockout will automatically update binded html with new values.

Tags: Orchard, C#, SignalR, Knockout.Js


© 2017 Bunny's Attack