Friday, December 21, 2012

Using SignalR in ASP.Net MVC


I assume that you already know what SignalR is and this post is only a step by step guide to start using SignalR in an ASP.Net MVC application. Our  working environment will be:

Visual Studio(VS) 2010
ASP.Net MVC 4
SignalR 1.0
  
Create an ASP.Net MVC Solution

Create a new ASP.Net MVC 4 solution: Open VS and select “File>New>Project” and select “ASP.Net MVC 4 Web Application”. Name the application as “AspDotNetMvc.Integrate.SignalR” and click OK. On the next screen select “Empty” template and click OK. Now, VS will create the following project hierarchy as follows:



Under “Controllers”, create a new controller as follow:

using System.Web.Mvc;

namespace AspDotNetMvc.Integrate.SignalR.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

    }
}

Then, under “Views” create a view for our HomeController’s Index action as follow (Here, I created the view without a layout page and with the default Razor engine:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        "Hello SignalR"
    </div>
</body>
</html>

Now, run the project and we’ll see the browser with the text “Hello World”. Now our solution will be like below:



Install SignalR

Now, we need to get SignalR from NuGet. For this, go to “Tools>Library Package Manager>Package Manager Console” and type the following and press enter:

Install-Package Microsoft.AspNet.SignalR –pre

NuGet will install SignalR in our solution and the structure will look like below:



Notice that NuGet has added 2 new javascript files. In our folder structure, we can see a new folder called “packages”


And, under Packages, we can see all the dll’s that NuGet downloaded for us:


Here are the references that NuGet added for the needed DLL’s in our project.


Using SignalR: Server Side

Let’s use SignalR to create a tweet application where users can submit a tweet and then it will be broadcasted to all the connected users.  Create a folder called “Hubs” under root, and then create a class in that folder called “Tweet”.

using Microsoft.AspNet.SignalR.Hubs;

namespace AspDotNetMvc.Integrate.SignalR.Hubs
{
    public class Tweet:Hub
    {
        public void SendTweet(string tweetText)
        {
            Clients.All.addTweet(tweetText);
        }
    }
}

This class is called a hub and it derived from the SignalR’s Hub base class. The clients will send new tweets to the SendTweet method in our tweet hub and then it will broadcast it to all the connected clients by calling the “addTweet” javascript method.

Now, add the line “RouteTable.Routes.MapHubs();”  in the “Aplication_Start” method in the Global.asax file. This method will create the mapping to the dynamically created javascript file “~/signalr/hubs” that is discussed in the client side section below.

public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
RouteTable.Routes.MapHubs();
AreaRegistration.RegisterAllAreas();

WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}

That’s all we have to do on the server side.

Using SignalR: Client Side

To set up the client side, add the following scripts in the html head of the Index view,:

<script src="~/Scripts/jquery-1.6.4.min.js" type="text/javascript"> </script>
<script src="~/Scripts/jquery.signalR-1.0.0-rc1.min.js" type="text/javascript"> </script>
<script type="text/javascript" src="~/signalr/hubs"> </script>

Here, first we add JQuery as SignalR needs it, then we add the javascript for SignalR. Next line with the src attribute “~/signalr/hubs” points to a dynamically created javascrip file on the server by SignalR. Below is our current structure of the solution and you can see that there is no folder at root called “SignalR” and, thus, make sure that we don’t create any folder by the name “SignalR” at the root.



Now, create the user interface for our tweets. Add a textbox and a button to send tweets to the server and a list to add new tweets sent by the server:

<div>    
            <input type="text" id="msg" />
            <input type="button" id="broadcast" value="Send Tweet" />
            <ul id="messages"></ul>
        </div>

Next step is to wire up the client with the server tweet hub. For this, add the following script at the end of the head:

<script type="text/javascript">
$(function() {
           var tweetProxy = $.connection.tweet;

           tweetProxy.client.addTweet = function (message)
           {
                 $('#tweet-list').append('<li>' + message + '</li>');
           };

           $.connection.hub.start().done(
                 function () {
                     $("#send-tweet").click(
                          function() {
                          tweetProxy.server.sendTweet($('#tweet').val());
                      });
                 });
});
</script>

Here, we first create a proxy to talk with the server with the line “$.connection.tweet”. In the next line, we have the “addTweet” javascript function that the server will use to call the browser. In this method, we will simply add the new tweets sent by the server to our tweet list that we created on the html body. The last line, we start the proxy and bind the “Send Tweet” buttons’ click event to send the value in the text box to our tweet hub.  Now, our Index view should look like below with the newly added code highlighted in yellow:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
        <script src="~/Scripts/jquery-1.6.4.min.js" type="text/javascript"> </script>
<script src="~/Scripts/jquery.signalR-1.0.0-rc1.min.js" type="text/javascript"> </script>
        <script type="text/javascript" src="~/signalr/hubs"> </script>
        <script type="text/javascript">
$(function() {
           var tweetProxy = $.connection.tweet;

           tweetProxy.client.addTweet = function (message)
           {
                 $('#tweet-list').append('<li>' + message + '</li>');
           };

           $.connection.hub.start().done(
                 function () {
                     $("#send-tweet").click(
                          function() {
                          tweetProxy.server.sendTweet($('#tweet').val());
                      });
                 });
});
        </script>
    </head>
    <body>
       
        <div>
            "Hello SignalR"
        </div>
       
        <div>    
            <input type="text" id="msg" />
            <input type="button" id="broadcast" value="Send Tweet" />
            <ul id="messages"></ul>
        </div>
    </body>
</html>

That’s all we need to do, now, let’s see our efforts in action. Run the project and open two separate browsers. In each browser, navigate to the local site:


On the left browser, type “Tweet: Left Browser” and press “Send Tweet” and the message will appear in both browsers:


On the right browser, type “Tweet: Right Browser” and press “Send Tweet” and the message will appear in both browsers:

That’s it. You can find this project on GitHub: https://github.com/sujeewa/AspDotNetMvc.Integrate.SignalR.git

No comments:

Post a Comment