A very basic introduction to using WebSockets technology in your brand new ASP.NET 5 web project. This article includes concepts of middleware and basic network communication information.

Before you start reading the code please understand that the source examples are meant to be as simple as possible. In a real-world implementation I advise you to follow SOLID principles and encapsulate the behaviour into classes and methods.

ASP.NET 5 Middleware

It’s important to understand how ASP.NET request processing pipeline is structured. It’s using a stack of middleware implementations of connection and request handlers. MVC and WebSocket handlers are out-of-the-box implementations which you can use.

When a request is received it goes through the middleware stack and gets processed accordingly. Any middleware can stop the request from being executed any further, or pass it downstream after processing it.

Plug it in

You can choose to start with an empty project or a yeoman generated template. First step is to make sure you’ve got the socket package installed:

"Microsoft.AspNet.WebSockets.Server": "1.0.0-rc1-final"

Note that the version may change as the package is updated.

Next step is to plug in the middleware. Open Startup.cs file and add the following code. Make sure you place it above app.AddMvc(…) if you chose to use MVC.

app.UseWebSockets();

app.Use(async (http, next) =>

{

if (http.WebSockets.IsWebSocketRequest)

{

var webSocket = await http.WebSockets.AcceptWebSocketAsync(); if (webSocket != null && webSocket.State == WebSocketState.Open)

{

// TODO: Handle the socket here.

}

}

else

{

// Nothing to do here, pass downstream.

await next();

}

});

//app.UseMvc(...) here if required.

This code is a starting point to the WebSockets goodness in ASP.NET 5. It’s now time to start handling the socket requests.

Understand requests

The object we’ve declared as webSocket variable represents single network connection and it operates in multiple states. Every time we do any request handling or responding through the socket we need to make sure we do it when it’s state is Open and we should avoid losing the object reference.

We’ll start off with a simple loop and we’ll await for a text message to be received:

while (webSocket.State == WebSocketState.Open)

{

var token = CancellationToken.None;

var buffer = new ArraySegment<Byte>(new Byte[4096]);



// Below will wait for a request message.

var received = await webSocket.ReceiveAsync(buffer, token);



switch (received.MessageType)

{

case WebSocketMessageType.Text:

var request = Encoding.UTF8.GetString(buffer.Array,

buffer.Offset,

buffer.Count);

// Handle request here.

break;

}

}

In the simple example above we are handling only Text messages. Now we have our message receiving bits, which we can then take action upon. In more advanced scenarios we could handle more message types and change how we process requests based on socket state changes.

Note that there is also Binary message type available for streaming files, audio and video. This will not be covered in this article.

Issue responses

WebSocket is a two way connection. This means we can send messages to clients anytime we want. This can be used to broadcast notifications (server-client) or responses (client-server-client). All we have to do is to build a response and pass it as a buffer to the socket connection.

var token = CancellationToken.None;

var type = WebSocketMessageType.Text;

var data = Encoding.UTF8.GetBytes(text);

var buffer = new ArraySegment<Byte>(data); await socket.SendAsync(buffer, type, true, token);

Manage subscriptions

It is very useful to keep track of all active socket connections. This approach allows the server to do broadcasts to multiple connected clients. A good way of handling this is to use a ConcurrentBag.

Every time we get a new WebSocket connection we’ll add it to our list when it enters the Open state. Declare a singleton ConcurrentBag<WebSocket> and change the initial bits:

var _sockets = new ConcurrentBag<WebSocket>();

Update the middleware:

var webSocket = await http.WebSockets.AcceptWebSocketAsync(); if (webSocket != null && webSocket.State == WebSocketState.Open)

{

if (_sockets.TryAdd(webSocket))

{

// TODO: Handle the socket here.

}

}

Now there is a list of connections ready for us to use. I advise to use asynchronous code to issue any messages and check if the listed connections are Open.

await Task.WhenAll(_sockets.Where(s.State == WebSocketState.Open)

.Select(s => s.Send(…));

Summary

I hope the article helped getting you started developing WebSockets on ASP.NET 5. The above examples show a very basic setup, which may work for some, but really I recommend implementing SOLID principles. The asynchronous model of socket programming is difficult to test, but if you follow the principles of good design, then you will be able to write tests that will ensure solid functionality.

Any questions or suggestions feel free to leave them in the comments. As always, thanks for dropping by.