“ASP.NET SignalR is a new library for ASP.NET developers that makes it incredibly simple to add real-time web functionality to your applications.” as stated on the official site of SignalR.
Recently I needed to find a solution that supports push-like notifications for a SharePoint 2010 web-based administration tool that should run in the background but should send notifications occasionally to the user started the request. Most of the forum discussions suggested SignalR, and the information and samples I found about this library on the web (like the above-mentioned official site or these tutorials) were really convincing.
Probably the most difficult part of the SharePoint 2010 – SignalR integration is the different .NET Framework version they use (.NET Framework 3.5, that is Common Language Runtime (CLR) 2.0 vs. .NET Framework 4.5, that is CLR 4.0). To bridge this gap we should include some kind of out-of-process communication channel (typically HTTP-based) that mediates between the parties.
Unfortunately, most of the SharePoint-related samples are either jokes (like the April Fools post about SharePointR exactly 2 years ago), outdated (for example using SignalR 1.x, like this solution), and / or based on SharePoint 2013 (like the posts here, here or this CodePlex solution).
To to make a long story short, I decided to create my own implementation for SharePoint 2010 using SignalR 2.0, and base the implementation on a WCF service as opposed to this HTTP Handler-based solution.
My solution contains four projects:
TaskNotifierService is an IIS hosted WCF service that acts as the SignalR Hub as well. It is a CLR 4.0 process.
TaskNotifierTestConsole is a console application based on the .NET Framework 4.5. Again, the framework version is not important, any version that supports WCF would be OK. This application can be used to send test messages to the WCF host, and thus test the code that creates the WCF client proxy and calls the WCF service methods. Using this project we can test the functionality without SharePoint as well. If your goal is just to send test messages, but you are not interested in the code itself, you can use the WCF Test Client of Visual Studio either (more about that later).
Below is the architecture of these components including the possible connections between them. The core and indispensable component is the TaskNotifierService. The other components are optional. For example you can use either the TaskNotifierTestConsole, the SPTaskNotifier or the WCF Test Client to sent messages (e.g. call the WCF service method) to the TaskNotifierService, and it will forward the messages to the adequate client, let it be either the TaskNotifierTestWeb or the SPTaskNotifier.
We start our code review with the core component, the TaskNotifierService. We define the data and service contracts of our WCF service in this project.
The TaskNotification is the data contract of the communication. It includes the Title of the new task, the LoginName of the user the task is assigned to and the URL of the display form of the task item.
The ITaskNotifierService interface is the service contract, including only a single method called TaskCreated. This method has a single parameter of type TaskNotification.
The TaskNotifierService class implements the ITaskNotifierService interface. In the implementation of the TaskCreated method we first get an instance of the current ConnectionManager then get the hub context via its GetHubContext<TaskNotifierHub> method. Finally we collects the client connections using the contextfor the user the task was assigned to (taskNotification.LoginName) and call the addTaskMessage method of these connections including the task title and URL as parameters (taskNotification.Title and taskNotification.Url):
Note: We call the ToUpper method on the LoginName to make it case-insensitive, see the same for the Context.User.Identity.Name in the OnConnected method of the TaskNotifierHub below.
Our TaskNotifierHub class is a subclass of a SignalR Hub class. Whenever a new client is connected to the hub, we determine the user name corresponding the connection and assign the connection ID to the group identified by the user name.
The Startup class is responsible for the startup of our service hub. In its Configuration method we set up the configuration settings that enable accessing the hub from an external web site (see CORS, Cross-Origin Resource Sharing) and finally start the SignalR pipeline.
The second project, TaskNotifierTestConsole is a simple WCF client to test the WCF service hosted in IIS (see TaskNotifierService above), so a Service reference to the TaskNotifierService was added to this project.
In the SendTaskNotification method we create a WCF proxy instance and call its TaskCreated method with the test parameters.
The configuration of the proxy (WCF bindings, etc.) are set from code, see TaskNotifierProxy property later at the TaskCreated event receiver of the SPTaskNotifier project. Of course, you could set the same values from a configuration file as well.
Important, that Windows Authentication should be enabled for the web site, otherwise the hub cannot determine the user name on the client connection.
The SPTaskNotifier is a simple SharePoint project that includes an event receiver that is triggered whenever a new item is created in a Tasks list.
First, we register our event handler to all lists created from the Tasks list template:
In the ItemAdded method of the TaskCreated class we determine the Title and the owner of the new task, as well as the URL of the display form, and call the SendTaskNotification method with this parameters.
The SendTaskNotification method is very similar to the version we saw in the case of the TaskNotifierTestConsole project above, but includes a few lines that help debugging and tracing.
Since we call the TaskNotifierService, we should add a Service reference to this project as well. The WCF client proxy is configured dynamically from code.
TaskNotifierLoader.js support dynamic loading of the necessary jQuery and SignalR libraries as well as our other .js file, the TaskNotifier.js.
TaskNotifier.js performs the same SignalR hub-related tasks as we saw at the default.htm of the TaskNotifierTestWeb project above, but in this case we display the notification as a standard SharePoint status message.
Testing the Solution
Be sure you start the TaskNotifierService project first. As I mentioned, it is the core, without that the other components won’t work.
Next, you can start the UI components, that means opening either SharePoint or the test web project in the browser. If you start the UI first, the client can’t register itself at the SignalR hub so it won’t receive any notifications later.
You can test the SignalR hub and the web UI (either the test project or the SharePoint solution) using the WCF Test Client.
You can select the TaskCreated method, set the parameter values you would like to pass to the method, and invoke the method.
A few important things to note regarding this tool:
You should use a double backslash to separate the domain and user names in the LoginName parameter, as there is a bug in the WCF Test Client.
You might get an error message when you start the WCF Test Client:
Error: Cannot obtain Metadata
In this case you should read the full error message as it may have a rather trivial solution like the lack of free memory in this case:
Memory gates checking failed because the free memory (xxxxxxxx bytes) is less than 5% of total memory. As a result, the service will not be available for incoming requests. To resolve this, either reduce the load on the machine or adjust the value of minFreeMemoryPercentageToActivateService on the serviceHostingEnvironment config element.
Here is a sample output of calling the TaskCreated method from the WCF Test Client with the parameters displayed on the screenshot above using the test web site (see TaskNotifierTestWeb project):
And the result of the same call in SharePoint:
Alternatively, you can test the functionality from the TaskNotifierTestConsole project as well. The following screenshots display the result of calling the TaskCreated method from the TaskNotifierTestConsole project in the case of the test web project:
And in the case of the SharePoint solution:
Note: The user can close the SharePoint status messages as described in my former post.
Of course, the main goal of this post and the sample is to illustrate, how to use SignalR 2.0 from SharePoint, so let’s see how it works. In this case, I suggest you to start two separate browser tabs, one for the Task list and an other one with an arbitrary page on the same SharePoint site. The reason of this is that when you create a new task, the page is reloaded and you might miss the notification. You should receive the notification in the other browser window.
So let’s create a new task and assign it to the current user.
A new status message will be displayed in the other browser tab.
Clicking on the hyperlink will open the display form of the task just created.
Hopefully you can apply the techniques illustrated here to add real-time functionality easily to your SharePoint applications via the SignalR libraries.
You can download the source code of the sample application from here.