Introduction
There are many tutorials for creating a chat application in MVC using SignalR (here). We can use this same concept to allow SharePoint app parts to communicate with each other. SharePointers usually face this problem where they want their app parts to convey some information to each other. Since these app parts are in two different Iframes, they don’t have many options of communicating with each other in real time. We can use SignalR to solve this problem.
Background
After reading this tip, you will be able to create a SharePoint app part that displays the survey results chart that is updated at the instant someone submits a vote in the other app part. So one app part acts as the sender and one receiver, unlike a chat app where both the clients act as senders and receivers.
Steps
- To start with, create a provider-hosted (MVC) SharePoint app using Visual Studio 2013
- The MVC app must have two views: One view that allows user to vote on certain Survey Questions and other view that shows the current survey result in the form of a pie chart. (I have used SharePoint lists to store questions and answers and the corresponding vote count.)
- Once you are done with the two views and your app is up and running, install the Nuget package ASP.NET SignalR in the MVC app from package manager or from command line.
- Add an OWIN startup class file: Select Add new Item to project. Then select OWIN Startup Class. Put the below code in the
Configuration
function:
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
- Add SignalR Hub class: Select add new item to the project. Then select SignalR Hub Class. Add the below function in the class. This is a server method in which we call the client method on the all/ specific clients.
public void notifyVotes(string user, SurveyModel data)
{
Clients.All.showNotifiedVotes(user, data);
}
So here notifyVotes
is a server method which calls showNotifiedVotes
method defined on all clients.
- Code for sender (view that allows user to vote on certain Survey Questions): The sender needs to call the server method of the hub class with the data that is to be sent to the clients. This is done in an event handler that should trigger this broadcast. In our case, that would be the Vote button click handler. So here goes the code for that:
$(document).ready(function () {
$.connection.hub.start().done(function () {
$('.submitVote').click(function () {
var surveyId = $(".survey:Visible").attr('id');
var currentSurveyDiv = $(".survey#" + surveyId);
var selectedAnswer = $(currentSurveyDiv.find
($("input[name='SelectedAnswer']:checked"))).val();
$.ajax({
type: 'POST',
data: { SurveyId: surveyId, SelectedAnswer: selectedAnswer },
url: "Survey/SubmitVote",
success: function (data, textStatus, jqXHR) {
var theHub = $.connection.theHub;
theHub.server.notifyVotes(data.user, data.data);
},
error: function (jqXHR, textStatus, errorThrown) {
console.log('Error: ' + errorThrown);
}
});
});
});
});
So we define the handler for submit vote button. The important thing to remember is the handler must be registered after the connection start method of the hub is 'done' or succeeded. So the jquery click handler is put in the callback function of the start
method. As the ajax POST request that updates the votes in SharePoint list succeeds, the server method in the hub is called with the Id of the survey that was updated and the user who updated it.
- Code for receiver (view that shows the current survey result in the form of a pie chart):
$(document).ready(function() {
$.connection.hub.start();
});
function showNotifiedVotes(user, data) {
var surveyId = data.SurveyId;
$.ajax({
type: 'GET',
data: { SurveyId: surveyId },
url: "SurveyChart/GetSurveyChart",
success: function (data, textStatus, jqXHR) {
$(".surveyChartWrapper#" + surveyId).empty().html(data);
$(".surveyChartWrapper:Visible").hide();
$(".surveyChartWrapper#" + surveyId).show();
var nextSurveyId = parseInt(surveyId) + 1;
if ($(".surveyChartWrapper#" + nextSurveyId).length > 0)
$("#btnNext").show();
else
$("#btnNext").hide();
},
error: function (jqXHR, textStatus, errorThrown) {
console.log('Error: ' + errorThrown);
}
});
var encodedMsg = $('div').text(user + " just voted for " +
data.SelectedAnswer ).html(); toastr.warning(encodedMsg);
- Add a reference to the below script files in both sender and receiver view.
- "~/Scripts/jquery-1.10.2.min.js"
- "~/Scripts/jquery.signalR-2.2.0.min.js"
- "~/signalr/hubs"
- Combined API for all SignalR JavaScript operations:
Just to have the SignalR code at one place instead of scattering it over different views, I added one js file SignalR .API.js which has 3 methods.
initReceiver
: contains the receiver's code. Called in doc.ready
event handler of the receiver initSender
: contains the event handler for submit vote button startConnection(callback)
: which starts a connection and accepts a callback function which is called in the 'done' success handler of the start
method.
Here is how the sender and receiver code look like now:
SignalR_API.startConnection(SignalR_API.initSender);
SignalR_API.initReceiver();
SignalR_API.startConnection();
- Run the app. Open up two views in two separate windows. Hit the Vote button and voila! You can see that the pie chart is re-rendered and it shows the updated survey result.
Now you can add these two views as App parts on your SharePoint tenant page and you will have two app parts that are communicating with each other using SignalR. To know how to add MVC views as app parts in SharePoint, check out my blog.