Tuesday, June 21, 2016

Integrating SignalR with ASP.NET Web API

In this post let’s see how we can integrate and trigger SignalR with ASP.NET Web API. Let’s start off by creating a solution and adding a ASP.NET Web API project and empty ASP.NET project. Let’s set the API project’s Project URL to {web_app_project_url}/api, so it will run under the Web App Project URL. And we need to modify the DefaultApi route to remove explicit “api” part as follows.
config.Routes.MapHttpRoute(
   name: "DefaultApi",
   routeTemplate: "{controller}/{id}",
   defaults: new { id = RouteParameter.Optional }
);
Now let’s install SignalR nuget package to the ASP.NET Web API project. You can use either Nuget Package Manager and Package Manager Console. I prefer using Package Manager Console by running Install-Package Microsoft.AspNet.SignalR.

image
Install-Package Microsoft.AspNet.SignalR
Now open up the Startup.cs in the Web API project and bootstrap SignalR as follows.
using Microsoft.Owin;
using Owin;
 
[assembly: OwinStartup(typeof(AspNetWebApiSignalRDemo.WebApi.Startup))]
 
namespace AspNetWebApiSignalRDemo.WebApi
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
            app.MapSignalR();
        }
    }
}
Now let’s create a folder inside Web API project named “Hubs” and add a SignalR Hub Class. I am naming it as “NotificationHub”.
image
SignalR Hub Class
The created file will contain a Hello() method, and I am just leaving it as it is.

Now let’s move into the empty web app project. For the sake of demonstration, I am using AngularJS to bootstrap the web app project. For that I am installing following dependencies using  bower.
image
bower dependencies
index.html
<!DOCTYPE html>
<html ng-app="AspNetWebApiSignalRDemo">
 
<head>
    <script src="bower_components/jquery/dist/jquery.min.js"></script>
    <script src="bower_components/signalr/jquery.signalR.min.js"></script>
    <script src="bower_components/angular/angular.min.js"></script>
    <script src="api/signalr/hubs"></script>
    <script src="app.js"></script>
 
    <title>ASP.NET Web API and SignalR Demo</title>
    <meta charset="utf-8" />
</head>
<body>
    <div ng-controller="AppController">
        
    </div>
</body>
</html>
app.js
'use strict';
 
angular.module("AspNetWebApiSignalRDemo", [])
 
.service("SignalrService", function () {
    var notificationHubProxy = null;
 
    this.initialize = function () {
        $.connection.hub.logging = true;
        notificationHubProxy = $.connection.notificationHub;
 
        notificationHubProxy.client.hello = function () {
            console.log("Hello from ASP.NET Web API");
        };
 
        $.connection.hub.start().done(function () {
            console.log("started");
        }).fail(function (result) {
            console.log(result);
        });
    };
})
 
.controller("AppController", ["SignalrService", function (SignalrService) {
    SignalrService.initialize();
}]);
Now if you run the solution, you will see that SignalR is making a successful connection with my NotificationHub in the ASP.NET Web API project.
image
SignalR connected successfully
To make sure whether we can invoke client side methods from the Web API project, let’s use the NotificationHub from a API action. For that I am modifying the NotificationHub class adding a static method as follows.
using Microsoft.AspNet.SignalR;
 
namespace AspNetWebApiSignalRDemo.WebApi.Hubs
{
    public class NotificationHub : Hub
    {
        private static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>(); 

        public void Hello()
        {
            Clients.All.hello();
        }
 
        public static void SayHello()
        {
            hubContext.Clients.All.hello();
        }
    }
}
And let’s just modify Get() action in ValuesController as follows. Please note that I am attributing it with [AllowAnonymous], so I can access directly from the browser without authenticating.
[AllowAnonymous]
public IEnumerable<string> Get()
{
    NotificationHub.SayHello();
 
    return new string[] { "value1", "value2" };
}
And now if you invoke the /api/values from the browser, you will see that Web API is triggering client hub event "hello".
image
Web API + SignalR
I have made the sample code available in GitHub.
   AspNetWebApiSignalRDemo

Happy Coding.

Regards,
Jaliya