Wednesday, January 22, 2014

Using SignalR in an Asp.Net MVC 5 project: basic setup and Unity integration

This article covers the basic setup and Unity integration of using SignalR in a MVC project.

1.    Basic Setup

There are three steps in using SignalR in MVC:
·         Adding SignalR library;
·         creating OWIN startup classes to setup SignalR route;
·         writing server side and client side code.

First you need to use NuGet to install Microsoft.AspNet.SignalR package.
install-package Microsoft.AspNet.SignalR
This will install both server side packages and client side JavaScript libraries into your MVC project.
Then you need to configure SignalR routes in application startup. Create a C# class file (the filename and location doesn’t matter but a recommended one is “SignalRStartup.cs” in App_Start folder) with the following content (code snippets are copied or modified from examples in http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/tutorial-getting-started-with-signalr-20):
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(MyNamespace.SignalRStartup))]
namespace MyNamespace
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // Any connection or hub wire up and configuration should go here
            app.MapSignalR();
        }
    }
}

In the server side, you need to create a Hub subclass in your controller folder. A sample is
using System;
using System.Web;
using Microsoft.AspNet.SignalR;
namespace SignalRChat
{
    public class ChatHub : Hub
    {
        public void Send(string message)
        {
            // Call the broadcastMessage method to update clients.
            Clients.Others.broadcastMessage(message);
        }
    }
}

In your Web application, the View file should include "~/Scripts/jquery-{version}.js",,"~/Scripts/jquery.signalR-{version}.js" and "~/signalr/hubs".
In the client side, you need to call the server side method as well as define a method to be called by Server side method.  The code may look like the following:
var chat = $.connection.chatHub;
$.connection.hub.start().done(function () {
$('#sendmessage').click(function () {
        chat.server.send('Hello World');
    });
});
 
chat.client.broadcastMessage = function (message) {
    alert(message);
};

The JavaScript code use camel-cased version of the server method name.  The generated signalR proxy automatically convert a method name to a correct one. In the server side, there is no method name conversion. A server calls the camel-cased JavaScript client method.

2.    Working with Unity IoC container


After using NuGet to install Unity and Asp.Net SingalR packages, one needs to perform the following steps to resolve types for SignalR methods using a Unity container. There are two options to use Unity as dependency resolve in SignalR: one is to replace the whole SignalR dependency resolver; the other option is to only replace the IHubActivator component of the SignalR dependency resolve. The first one is document in http://www.asp.net/signalr/overview/signalr-20/extensibility/dependency-injection. It needs to implement two methods (GetService and GetServices) of SingalR IDependcyResolver interface. The second option only needs to implement one method of SingalR IHubActivator interface.

Not only the first option has more methods to be implemented, but also it needs future steps to allow type resolve in Hub classes. Therefore we choose to use the second option. The following steps are based on http://damienbod.wordpress.com/2013/11/05/using-signalr-with-unity/.
First, create a class implementing IHubActivator interface. In the class, use a Unity container in the IHub Create(HubDescriptor descriptor) method.

using System;
using Microsoft.AspNet.SignalR.Hubs;
using Microsoft.Practices.Unity;
 
namespace SignalRHostWithUnity.Unity
{
    public class UnityHubActivator : IHubActivator
    {
        private readonly IUnityContainer container;
 
        public UnityHubActivator(IUnityContainer container)
        {
            this.container = container;
        }
 
        public IHub Create(HubDescriptor descriptor)
        {
            if (descriptor == null)
            {
                throw new ArgumentNullException("descriptor");
            }
 
            if (descriptor.HubType == null)
            {
                return null;
            }
 
            object hub = this.container.Resolve(descriptor.HubType) ?? Activator.CreateInstance(descriptor.HubType);
            return hub as IHub;
        }
    }
}

Next, set SingalR Hub resolver in the Unity configuration file.  There is no need to register IHubActivator in Unity as described in the above reference because this interface is only used by SignalR and should be registered only in the SignalR dependency resolver.  
var container = new UnityContainer();
GlobalHost.DependencyResolver.Register(

    typeof(IHubActivator), 

    () => new UnityHubActivator(container));

Finally, register every application Hub class in the Unity configuration file.
container.RegisterType<MyHub, MyHub>(new TransientLifetimeManager());

Together, the Unity configuration file looks like below:
var container = new UnityContainer();
container.RegisterType<MyHub, MyHub>(new TransientLifetimeManager());
 
… // register other types
 
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
 
GlobalHost.DependencyResolver.Register(

    typeof(IHubActivator), 

    () => new UnityHubActivator(container));
 



2 comments: