SignalR is an open source framework allowing bi-directional communication between client and server. Basically, it uses a stack of technologies; the idea being that the Signalr framework will establish the “best” way to maintain a bi-directional data stream, starting with web sockets, and falling all the way back to simply polling the server.
The following gives the basics of establishing a web site that can accept Signalr, and a console app that can send messages to it.
Create project
Let’s go MVC:
Hubs
Hubs are the way in which the Signalr service communicates with its clients. Obviously, the term service here may not actually represent a service.
To add a hub class, select the project, right-click and “New Item..“:
This adds the file, along with new references:
The code above that gets added is:
public void Hello()
{
Clients.All.hello();
}
Clients.All returns a dynamic type, so we lose intellisense at this point. It’s important that the signature of this method is exactly correct, and that it is decorated with the name of the hub, and that it is decorated with the name of the hub; so let’s replace with:
[HubName("MyHub1")]
public class MyHub1 : Hub
{
public void Hello(string message)
{
Clients.All.Hello(message);
}
}
Change Startup.cs:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
app.MapSignalR();
}
}
For all this to actually do anything, the next thing to do is hook up the JavaScript:
$(function () {
// Declare a proxy to reference the hub.
var hub = $.connection.MyHub1;
// Create a function that the hub can call to broadcast messages.
hub.client.hello = function (message) {
alert("Hello");
};
$.connection.hub.start()
.done(function () { console.log("MyHub1 Successfully Started"); })
.fail(function () { console.log("Error: MyHub1 Not Successfully Started"); })
});
Effectively, once we receive a message, we’re just going to display an alert. Once the event handler is wired up, we try to start the hub.
Next, reference the required files in BundleConfig.cs:
bundles.Add(new ScriptBundle("~/bundles/signalr").Include(
"~/Scripts/jquery-3.1.1.min.js").Include(
"~/Scripts/jquery.signalR-2.2.1.js"));
These are referenced in _Layout.cshtml; remember also that, because SignalR references Jquery, you’ll need to remove other references to Jquery:
[code lang=“HTML”]
. . .
[code lang="HTML"]
</div>
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
Notes on Bundles
The purpose of bundling is to shrink the size of the bundled files. The idea being that small files make for a speedy web-site.
Console App
The next step is to create an application that can fire a notification to the page. In this case, I’m using a console app, just because I like to see everything working with console apps.
Start with a NuGet Reference:
The code:
class Program
{
static void Main(string[] args)
{
Console.Write("Message: ");
string message = Console.ReadLine();
HubConnection connection = new HubConnection("http://localhost:4053/");
IHubProxy hub = connection.CreateHubProxy("myHub1");
connection.Start().Wait();
hub.Invoke<string>("Hello", message).Wait();
Console.WriteLine("Sent");
Console.ReadLine();
}
}
And that’s it - you should be able to send a message to the web site from the console app. The examples that are typically given elsewhere on the net are chat rooms, but this clearly has many more uses.
Some abstract notes that I made while researching this.
Adding:
Version 1
protected void Application\_Start()
{
AreaRegistration.RegisterAllAreas();
>RouteTable.Routes.MapHubs(new HubConfiguration());
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
…
Gives:
Severity Code Description Project File Line Source Suppression State Error CS0619 ‘SignalRRouteExtensions.MapHubs(RouteCollection, HubConfiguration)’ is obsolete: ‘Use IAppBuilder.MapSignalR in an Owin Startup class. See http://go.microsoft.com/fwlink/?LinkId=320578 for more details.’ SignalRTest3 C:\Users\Paul\documents\visual studio 14\Projects\SignalRTest3\SignalRTest3\Global.asax.cs 18 Build Active
This was for v1 Signal R - superseded in 2.
CORS
During trying to get this working, the prospect of using CORS came up. This enables cross domain requests, which are typically prohibited.
Proxies
The generated Proxy can be viewed (navigate to http://localhost:4053/signalr/hubs):
$.hubConnection.prototype.createHubProxies = function () {
var proxies = {};
this.starting(function () {
// Register the hub proxies as subscribed
// (instance, shouldSubscribe)
registerHubProxies(proxies, true);
this.\_registerSubscribedHubs();
}).disconnected(function () {
// Unsubscribe all hub proxies when we "disconnect". This is to ensure that we do not re-add functional call backs.
// (instance, shouldSubscribe)
registerHubProxies(proxies, false);
});
proxies['MyHub1'] = this.createHubProxy('MyHub1');
proxies['MyHub1'].client = { };
proxies['MyHub1'].server = {
hello: function (message) {
return proxies['MyHub1'].invoke.apply(proxies['MyHub1'], $.merge(["Hello"], $.makeArray(arguments)));
}
};
return proxies;
};
References:
https://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client
https://github.com/SignalR/SignalR/wiki/Faq
http://stackoverflow.com/questions/42108193/signalr-test-project-not-working-as-expected
http://www.jeffreyfritz.com/2015/05/where-did-my-asp-net-bundles-go-in-asp-net-5/