0

I am new to SignalR. I need to communicate to specific client

Here is what I have done so far

EmployeeHub.cs

using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;

namespace WebApplication1
{
    public class EmployeeHub : Hub
    {
        [HubMethodName("NotifyClients")]
        public static void NotifyCurrentEmployeeInformationToAllClients(string connectionID)
        {
            IHubContext context = GlobalHost.ConnectionManager.GetHubContext<EmployeeHub>();

            // update the specific connected client         
             context.Clients.Client(connectionID).updatedClients();
        }
    }
}

HomeController.cs

using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web.Mvc;
using WebApplication1.Models;

namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
        List<Employee> empList;

        //Fetch Employee Records
        public ActionResult Index()
        {
            return View();
        }
        [HttpGet]
        public ActionResult GetAllEmployeeRecords()
        {
            using (var context = new EmployeeContext())
            {
                empList = context
                .Employees
                .ToList();
            }          
            return PartialView("_EmployeeList", empList);
        }


        //Insert Employee Record
        public ActionResult Insert()
        {
            return View();
        }
        [HttpPost]        
        public ActionResult Insert(DataPacket dataPacket)
        {
            if (ModelState.IsValid)
            {
                //Insert into Employee table 
                using (var context = new EmployeeContext())
                {
                    context.Employees.Add(dataPacket.Employee);
                    context.SaveChanges();
                }
            }

            //Once the record is inserted , then notify(Clients)
            EmployeeHub.NotifyCurrentEmployeeInformationToAllClients(dataPacket.ConnectionID);
            return RedirectToAction("Index");
        }       
}

DataPacket.cs

public class Employee
    {
        [Key]
        public int EmployeeID { get; set; }
        public string EmployeeName { get; set; }
        public string EmailAdress { get; set; }
        public string MobileNumber { get; set; }      
    }

    public class DataPacket
    {
        public Employee Employee { get; set; }
        public string ConnectionID { get; set; }
    }

and finally my Index.cshtml

@model IList<WebApplication1.Models.Employee>
@{
    ViewBag.Title = "Index";
}
<link href="~/Content/bootstrap/css/bootstrap.min.css" rel="stylesheet" />

<div>    
        <h1 style="color: green">CRUD using SignalR,MVC and Entity Framework</h1>
        <table border="1">            
            ................................
        ................................
        </table>
    <br /><br />       
        <div id="dataTable"></div>
    </div>

@section JavaScript{
    <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
    <script src="/signalr/hubs"></script>
    <script type="text/javascript">

        $(function () {
            // Create a proxy to signalr hub on web server. It reference the hub.
            var notificationFromHub = $.connection.employeeHub;

            // Connect to signalr hub
            $.connection.hub.start().done(function () {
                FetchEmployees();
            });

            // Notify to client with the recent updates
            notificationFromHub.client.updatedClients = function () {
                FetchEmployees();
            };
        });

        function FetchEmployees() {
            var model = $('#dataTable');
            $.ajax({
                url: '/home/GetAllEmployeeRecords',
                contentType: 'application/html ; charset:utf-8',
                type: 'GET',
                dataType: 'html'
            })
                .success(function (result) { model.empty().append(result); })               
        }

        // Insert Employee Record
        function InsertEmployee()
        {


                    var employee = {
                        EmployeeID: $('#txtEmployeeId').val(),
                        EmployeeName: $('#txtEmployeeName').val(),
                        EmailAdress: $('#txtEmail').val(),
                        MobileNumber: $('#txtMobile').val(),                      
                    };

                    var dataPacket = {
                        Employee: employee,
                        ConnectionID: GenerateRandomNumbers()
                    }

                    $.ajax({
                    url: '/home/Insert',
                    type: 'POST',
                    data: JSON.stringify(dataPacket),
                    contentType: "application/json;charset=utf-8",
                    success: function (data) {
                        alert('Employee added Successfully');                       
                    },
                    error: function () {
                        alert('Employee not Added');
                    }
                });
        }        

        //Generate RandomNumbers
        function GenerateRandomNumbers() {
            var min = 1;
            var max = 10;
            return Math.floor(Math.random() * (max - min + 1) + min);
        }
    </script>
}

I am at present using a Random Number for generating the Client ID for Testing purpose. The problem is that, the record is added into the database but the notification to the client from SignalR is not happening until the Page loads.

E.g. This is the situation when I click on the "Add New Employee" Button.

enter image description here

Only the data gets reflected in the table when I do a page refresh like

enter image description here

I have refered to this SO Q/A also but I think I am missing something.

What is that I am missing ?

halfer
  • 19,824
  • 17
  • 99
  • 186
priyanka.sarkar
  • 25,766
  • 43
  • 127
  • 173

1 Answers1

1

In SignalR the ConnectionId is a specific number to a specific connected client. Therefore your ConnectionID: GenerateRandomNumbers() will not be the same connection id that your client is connected to.

To get the specific client connection id (specified here) you should capture the connectionID from the done() method of the initial Hub connection and store it as a global variable to your script.

Such as.

var connectionId = null;

$(function() {
//omitted code
    // Connect to signalr hub
    $.connection.hub.start().done(function () {

        connectionId = $.connection.hub.id;
        FetchEmployees();
    });
});

Then in your aJax call supply the actual Hub connection Id instead of the random numbers.

Finally to finish it off I would also provide a method to detect reconnections, disconnections etc as listed further down that guide to update \ clear the connection id in cases where it has changed or disconnected.

Nico
  • 12,493
  • 5
  • 42
  • 62