Using WebSocket in MVC4
Real time data update with MVC4 and HTML5 features
Ajax is really cool. You can pull your data without refreshing the whole page, but increasing user experience and downsizing bandwidth for website.
If you have some live data which is changing really often, the best way to display it on website is to use pulling mechanism. Simply invoke some resource for data on every few second or a minute.
This looks like a decent solution, but luckily with HTML there is WebSocket introduced. It is basically part of your browser and it is exposed to JavaScript so it can be invoked on a page. More details about what WebSocket really is you can find at http://en.wikipedia.org/wiki/WebSocket
We will not deal much how it actually works here, we'll more focus to how to use it on a simple MVC view to show some data in real-time.
So, here it goes. We will start with the JavaScript first. The following few lines of code are showing how simple it is to start websocket communication form the client side code.
$(document).ready(function () { var uri = "ws://localhost:8080/api/SocketClient"; //Initialize socket websocket = new WebSocket(uri); //Open socket and send message websocket.onopen = function () { $('#messages').prepend('<div>Connected to server.</div>'); websocket.send("Hello!"); }; //Socket error handler websocket.onerror = function (event) { $('#messages').prepend('<div>Ooooops! Some error occured</div>'); }; //Socket message handler websocket.onmessage = function (event) { $('#messages').prepend('<div>' + event.data + '</div>'); }; });
As you see it is really easy to implement them on client side. The real magic happens under the hood in MVC controller.
Websocket control is basically WebAPI controller, so you need to ensure that correct routing exists in in your App_Start/WebApiConfig.cs file
using System; using System.Collections.Generic; using System.Linq; using System.Web.Http; namespace C { public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } } }
There is one more thing to do before we skip to controller for WebSocket. In web.config file, section appSettings, add the following tag
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
Now we are ready to digg into controller's logic. Since we previously set our URL in JavaScript to target ws://localhost:8080/api/SocketClient and based on routing config for WebAPI our controller needs to be named SocketClient in order for script in a view to target it.
The following sample, is sending a message to WebSocket clients every second
namespace C.Controllers { public class SocketClientController : ApiController { public HttpResponseMessage Get() { HttpContext.Current.AcceptWebSocketRequest(new ChatWebSocketHandler()); return Request.CreateResponse(HttpStatusCode.SwitchingProtocols); } class ChatWebSocketHandler : Microsoft.Web.WebSockets.WebSocketHandler { private static WebSocketCollection _chatClients = new WebSocketCollection(); public override void OnOpen() { _chatClients.Add(this); } public override void OnMessage(string recordType) { for(int i=0;i<10;i++){ _chatClients.Broadcast(i.ToString()); System.Threading.Thread.Sleep(1000); } } } } }
The problem with web socket is that it does not work in all browsers, since not all of them are fully supporting WebSockets.
Detailed list of browsers supporting WebApi you can find at the following link http://caniuse.com/websockets
Luckily Microsoft has developed SignalR which is basically a wrapper around WebSocket and allows you to use WebSocket communication if it is supported by browser, if not it uses pulling mechanism described in the beginning of this article.
You can find out more at http://signalr.net
References
Disclaimer
Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.
Comments for this article