{"id":1944,"date":"2012-12-17T19:36:00","date_gmt":"2012-12-17T19:36:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/webdev\/2012\/12\/17\/signalr-building-real-time-web-applications\/"},"modified":"2012-12-17T19:36:00","modified_gmt":"2012-12-17T19:36:00","slug":"signalr-building-real-time-web-applications","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/signalr-building-real-time-web-applications\/","title":{"rendered":"SignalR: Building real time web applications"},"content":{"rendered":"<p>Note: This sample is targeting SignalR 1.0.1&#160; <\/p>\n<p><a href=\"https:\/\/github.com\/SignalR\/SignalR\">SignalR<\/a> offers a simple and clean API to write real time web applications where the server needs to continuously push data to clients. Common applications are chat, news feed, notifications, multiplayer games.<\/p>\n<p>In this sample, I demonstrate powerful features like:<\/p>\n<ul>\n<li>A server implementation hosted in IISExpress<\/li>\n<li>Client implementations running on IISExpress, a Console Application, a Windows Store App, and a Silverlight App<\/li>\n<li>Doing request\/response operations sync and async<\/li>\n<li>Server pushing broadcast messages to ALL clients<\/li>\n<li>Server pushing group messages to specific devices like a web browser, a desktop, or a tablet.<\/li>\n<\/ul>\n<h2>Server<\/h2>\n<p>Server derives the Hub class, and it handles incoming requests in two ways:<\/p>\n<ol>\n<li>Method &quot;y Request(x)&quot; transparently sends a response to client<\/li>\n<li>Method \u201cTask&lt;y&gt; RequestAsync(x)\u201d allows server to do async long processing and transparently sends a response to client<\/li>\n<li>Method &quot;Task RequestWithCallbackAsync(x)&quot; uses Clients.Others.&lt;DynamicMethod&gt; to send a response to all other clients connected at the moment<\/li>\n<\/ol>\n<table style=\"width: 720px\" cellspacing=\"0\" cellpadding=\"2\" border=\"1\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"720\">\n<pre class=\"code\"><span style=\"background: white;color: blue\">public class <\/span><span>SampleHub <\/span><span style=\"background: white;color: black\">: <\/span><span>Hub\n<\/span><span style=\"background: white;color: black\">{\n  <\/span><span style=\"background: white;color: blue\">public <\/span><span>FromServerToClientData <\/span><span style=\"background: white;color: black\">Request(<\/span><span>FromClientToServerData <\/span><span style=\"background: white;color: black\">request)\n  {\n    <\/span><span>FromServerToClientData <\/span><span style=\"background: white;color: black\">response = <\/span><span style=\"background: white;color: blue\">new <\/span><span>FromServerToClientData<\/span><span style=\"background: white;color: black\">();\n    response.Text = <\/span><span>&quot;Responding to: &quot; <\/span><span style=\"background: white;color: black\">+ request.Text;\n    <\/span><span style=\"background: white;color: blue\">return <\/span><span style=\"background: white;color: black\">response;\n  }\n\n  <\/span><span style=\"background: white;color: blue\">public async <\/span><span>Task<\/span><span style=\"background: white;color: black\">&lt;<\/span><span>FromServerToClientData<\/span><span style=\"background: white;color: black\">&gt; RequestAsync(<\/span><span>FromClientToServerData <\/span><span style=\"background: white;color: black\">request)\n  {\n    <\/span><span>FromServerToClientData <\/span><span style=\"background: white;color: black\">response = <\/span><span style=\"background: white;color: blue\">new <\/span><span>FromServerToClientData<\/span><span style=\"background: white;color: black\">();\n    response.Text = <\/span><span>&quot;Responding to: &quot; <\/span><span style=\"background: white;color: black\">+ request.Text;\n    <\/span><span style=\"background: white;color: blue\">await <\/span><span>Task<\/span><span style=\"background: white;color: black\">.Delay(<\/span><span>TimeSpan<\/span><span style=\"background: white;color: black\">.FromSeconds(5));\n    <\/span><span style=\"background: white;color: blue\">return <\/span><span style=\"background: white;color: black\">response;\n  }\n\n  <\/span><span style=\"background: white;color: blue\">public async <\/span><span>Task <\/span><span style=\"background: white;color: black\">RequestWithCallbackAsync(<\/span><span>FromClientToServerData <\/span><span style=\"background: white;color: black\">request)\n  {\n    <\/span><span>FromServerToClientData <\/span><span style=\"background: white;color: black\">response = <\/span><span style=\"background: white;color: blue\">new <\/span><span>FromServerToClientData<\/span><span style=\"background: white;color: black\">();\n    response.Text = <\/span><span>&quot;Responding to: &quot; <\/span><span style=\"background: white;color: black\">+ request.Text;\n    <\/span><span style=\"background: white;color: blue\">await <\/span><span>Task<\/span><span style=\"background: white;color: black\">.Delay(<\/span><span>TimeSpan<\/span><span style=\"background: white;color: black\">.FromSeconds(5));\n    Clients.Others.OthersCallback(response);\n  }\n\n  <\/span><span style=\"background: white;color: blue\">public void <\/span><span style=\"background: white;color: black\">JoinGroup(<\/span><span style=\"background: white;color: blue\">string <\/span><span style=\"background: white;color: black\">groupName)\n  {\n    Groups.Add(Context.ConnectionId, groupName);\n  }\n}<\/span><\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Server is also pushing data to clients in two ways using the BackgroundThread class:<\/p>\n<ol>\n<li>hubContext.Clients.All.&lt;DynamicMethod&gt;<\/li>\n<li>hubContext.Clients.Group(groupName).&lt;DynamicMethod&gt;<\/li>\n<\/ol>\n<table style=\"width: 720px\" cellspacing=\"0\" cellpadding=\"2\" border=\"1\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"720\">\n<pre class=\"code\"><span style=\"background: white;color: blue\">public class <\/span><span>BackgroundThread\n<\/span><span style=\"background: white;color: black\">{\n  <\/span><span style=\"background: white;color: blue\">public static void <\/span><span style=\"background: white;color: black\">Start()\n  {\n    <\/span><span>ThreadPool<\/span><span style=\"background: white;color: black\">.QueueUserWorkItem(_ =&gt;\n    {\n    <\/span><span>IHubContext <\/span><span style=\"background: white;color: black\">hubContext = <\/span><span>GlobalHost<\/span><span style=\"background: white;color: black\">.ConnectionManager.GetHubContext&lt;<\/span><span>SampleHub<\/span><span style=\"background: white;color: black\">&gt;();\n\n    <\/span><span style=\"background: white;color: blue\">while <\/span><span style=\"background: white;color: black\">(<\/span><span style=\"background: white;color: blue\">true<\/span><span style=\"background: white;color: black\">)\n    {\n      ...\n      hubContext.Clients.All.Broadcast(data);\n      hubContext.Clients.Group(<\/span><span>&quot;WebApp&quot;<\/span><span style=\"background: white;color: black\">).BroadcastToGroup(\n        <\/span><span style=\"background: white;color: blue\">string<\/span><span style=\"background: white;color: black\">.Format(<\/span><span>&quot;WebApp {0}&quot;<\/span><span style=\"background: white;color: black\">, <\/span><span>DateTime<\/span><span style=\"background: white;color: black\">.Now));\n      hubContext.Clients.Group(<\/span><span>&quot;ConsoleApp&quot;<\/span><span style=\"background: white;color: black\">).BroadcastToGroup(\n        <\/span><span style=\"background: white;color: blue\">string<\/span><span style=\"background: white;color: black\">.Format(<\/span><span>&quot;ConsoleApp {0}&quot;<\/span><span style=\"background: white;color: black\">, <\/span><span>DateTime<\/span><span style=\"background: white;color: black\">.Now));\n      hubContext.Clients.Group(<\/span><span>&quot;SilverlightApp&quot;<\/span><span style=\"background: white;color: black\">).BroadcastToGroup(\n        <\/span><span style=\"background: white;color: blue\">string<\/span><span style=\"background: white;color: black\">.Format(<\/span><span>&quot;SilverlightApp {0}&quot;<\/span><span style=\"background: white;color: black\">, <\/span><span>DateTime<\/span><span style=\"background: white;color: black\">.Now));\n      hubContext.Clients.Group(<\/span><span>&quot;WindowsStoreApp&quot;<\/span><span style=\"background: white;color: black\">).BroadcastToGroup(\n        <\/span><span style=\"background: white;color: blue\">string<\/span><span style=\"background: white;color: black\">.Format(<\/span><span>&quot;WindowsStoreApp {0}&quot;<\/span><span style=\"background: white;color: black\">, <\/span><span>DateTime<\/span><span style=\"background: white;color: black\">.Now));\n    }        \n    }\n  });\n}<\/span><\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>As you can see, dynamic methods define the events that need to be handled on the client side. Think of them as if they were interface methods to execute remote calls.<\/p>\n<p>&#160;<\/p>\n<h2>Client<\/h2>\n<p>To write a client, you must define how to handle Server &lt;DynamicMethods&gt;: &quot;client.Broadcast&quot;, &quot;client.Group&quot;, and &quot;client.ResponseAsync&quot;.<\/p>\n<p>Then, client is started, and after the connection succeeds, the client can make requests to server by invoking &quot;server.requestAsync&quot; and &quot;server.joinGroup&quot;.<\/p>\n<p>You will see similar patterns in the ConsoleApp and WindowsStoreApp clients.<\/p>\n<table style=\"width: 720px\" cellspacing=\"0\" cellpadding=\"2\" border=\"1\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"720\">\n<pre class=\"code\"><span style=\"background: white;color: black\">$(<\/span><span style=\"background: white;color: blue\">function <\/span><span style=\"background: white;color: black\">() {\n  $.connection.sampleHub.client.broadcast = <\/span><span style=\"background: white;color: blue\">function <\/span><span style=\"background: white;color: black\">(value) {\n    $(<\/span><span>'#BroadcastText'<\/span><span style=\"background: white;color: black\">).html(<\/span><span>'&lt;pre&gt;Broadcast: ' <\/span><span style=\"background: white;color: black\">+ value.Now + <\/span><span>' ' <\/span><span style=\"background: white;color: black\">+\n      value.Integer + <\/span><span>' ' <\/span><span style=\"background: white;color: black\">+ value.Text + <\/span><span>'&lt;\/pre&gt;'<\/span><span style=\"background: white;color: black\">);\n  }\n\n  $.connection.sampleHub.client.broadcastToGroup = <\/span><span style=\"background: white;color: blue\">function <\/span><span style=\"background: white;color: black\">(value) {\n    $(<\/span><span>'#BroadcastToGroupText'<\/span><span style=\"background: white;color: black\">).html(<\/span><span>'&lt;pre&gt;BroadcastToGroup: ' <\/span><span style=\"background: white;color: black\">+ value + <\/span><span>'&lt;\/pre&gt;'<\/span><span style=\"background: white;color: black\">);\n  }\n\n  $.connection.sampleHub.client.othersCallback = <\/span><span style=\"background: white;color: blue\">function <\/span><span style=\"background: white;color: black\">(value) {\n    $(<\/span><span>'#OthersCallbackText'<\/span><span style=\"background: white;color: black\">).html(<\/span><span>'&lt;pre&gt;OthersCallback: ' <\/span><span style=\"background: white;color: black\">+ value.Text + <\/span><span>'&lt;\/pre&gt;'<\/span><span style=\"background: white;color: black\">);\n  }\n\n  $.connection.hub.logging = <\/span><span style=\"background: white;color: blue\">true<\/span><span style=\"background: white;color: black\">;\n  $.connection.hub.start().done(<\/span><span style=\"background: white;color: blue\">function <\/span><span style=\"background: white;color: black\">() {\n    <\/span><span style=\"background: white;color: blue\">var <\/span><span style=\"background: white;color: black\">request = {};\n    request.Text = <\/span><span>'This is a request from a WebApp!'\n\n    <\/span><span style=\"background: white;color: black\">$.connection.sampleHub.server.request(request).done(<\/span><span style=\"background: white;color: blue\">function <\/span><span style=\"background: white;color: black\">(response) {\n      $(<\/span><span>'#ResponseText'<\/span><span style=\"background: white;color: black\">).html(<\/span><span>'&lt;pre&gt;Response: ' <\/span><span style=\"background: white;color: black\">+ response.Text + <\/span><span>'&lt;\/pre&gt;'<\/span><span style=\"background: white;color: black\">);\n    });\n    $.connection.sampleHub.server.requestAsync(request).done(<\/span><span style=\"background: white;color: blue\">function <\/span><span style=\"background: white;color: black\">(response) {\n      $(<\/span><span>'#ResponseAsyncText'<\/span><span style=\"background: white;color: black\">).html(<\/span><span>'&lt;pre&gt;ResponseAsync: ' <\/span><span style=\"background: white;color: black\">+ response.Text + <\/span><span>'&lt;\/pre&gt;'<\/span><span style=\"background: white;color: black\">);\n    });\n    $.connection.sampleHub.server.requestWithCallbackAsync(request);\n    $.connection.sampleHub.server.joinGroup(<\/span><span>'WebApp'<\/span><span style=\"background: white;color: black\">);\n  });\n});<\/span><\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>There is more information about how I wrote the code when running the sample, simply follow these instructions:<\/p>\n<ol>\n<li>Download and extract SignalR.Sample.zip<\/li>\n<li>On Visual Studio 2012, open SignalR.Sample.sln<\/li>\n<li>Right-click the solution and select &quot;Set Startup Projects\u2026&quot;<\/li>\n<li>Select &quot;Multiple startup projects&quot;, and set the projects in this order:<\/li>\n<ul>\n<li>SignalR.Sample<\/li>\n<li>SignalR.Sample.Client<\/li>\n<li>SignalR.Sample.WinRTClient<\/li>\n<\/ul>\n<li>Set &quot;Action&quot; column in all projects to &quot;Start&quot;. Click OK.<\/li>\n<li>Ctrl-F5 to run the projects, it will start a browser, a console app, and a windows store app.<\/li>\n<\/ol>\n<p>There are more advanced samples in the SignalR source code repository, follow these steps to get them:<\/p>\n<ol>\n<li>Install the latest <a href=\"http:\/\/code.google.com\/p\/msysgit\/downloads\/list\">Git for Windows<\/a><\/li>\n<li>Open a Command Prompt, create a folder, and download source code<\/li>\n<\/ol>\n<table style=\"width: 720px\" cellspacing=\"0\" cellpadding=\"2\" border=\"1\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"718\"><span style=\"font-family: courier new\">\n          <br \/>md C:\\SignalR\\release <\/p>\n<p>cd C:\\SignalR\\release <\/p>\n<p>git clone -b release <a href=\"https:\/\/github.com\/SignalR\/SignalR.git\">https:\/\/github.com\/SignalR\/SignalR.git<\/a> . <\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<ol>\n<li>On Visual Studio 2012, open C:\\SignalR\\release\\Microsoft.AspNet.SignalR.sln<\/li>\n<\/ol>\n<p>SignalR has recently shipped as RC, more details <a href=\"http:\/\/weblogs.asp.net\/scottgu\/archive\/2012\/12\/14\/announcing-the-asp-net-and-web-tools-2012-2-release-candidate.aspx\">here<\/a>. For the RTM version, I want to post a more complex sample, my idea is to demonstrate how to publish the server implementation on Azure and use scale-out with Service Bus. Please post a comment if you are interested to see something else.<\/p>\n<p><a href=\"https:\/\/msdnshared.blob.core.windows.net\/media\/MSDNBlogsFS\/prod.evol.blogs.msdn.com\/CommunityServer.Components.PostAttachments\/00\/10\/37\/88\/89\/SignalR.Sample.zip\">SignalR.Sample.zip<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Note: This sample is targeting SignalR 1.0.1&#160; SignalR offers a simple and clean API to write real time web applications where the server needs to continuously push data to clients. Common applications are chat, news feed, notifications, multiplayer games. In this sample, I demonstrate powerful features like: A server implementation hosted in IISExpress Client implementations [&hellip;]<\/p>\n","protected":false},"author":402,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[197],"tags":[7408],"class_list":["post-1944","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aspnet","tag-signalr"],"acf":[],"blog_post_summary":"<p>Note: This sample is targeting SignalR 1.0.1&#160; SignalR offers a simple and clean API to write real time web applications where the server needs to continuously push data to clients. Common applications are chat, news feed, notifications, multiplayer games. In this sample, I demonstrate powerful features like: A server implementation hosted in IISExpress Client implementations [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/1944","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/402"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=1944"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/1944\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=1944"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=1944"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=1944"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}