Practical .NET

Building a JavaScript WebSockets Client

Create a JavaScript client that works with a WCF 4.5 WebSockets service to receive continuous, ongoing updates from the service.

In my last two columns, I've looked at configuring and writing a WCF 4.5 Service. This service accepted an Order Id and then sent back the order's status. However, because I built the service using WCF 4.5's WebSockets support, the service isn't restricted to sending back a single result. Instead, the service could continue to update the client as the status in the order changed.

The first step in working with the service is to create the client-side object that represents it. You do that by instantiating the WebSocket object, passing the URL for your service. The only JavaScript library you need to reference is jquery-1.6.2. To open my service (called OrderStatus.svc in a site called WSSample) as soon as the page is ready, I could use this jQuery code:

var wss;
$(document).ready(function () 
 wss = new WebSocket("ws://localhost/WSSample/OrderStatus.svc");

The ws protocol used in the URL is required.

As I noted in my last column, the service can access the URL used to open its connection. For instance, if I wanted to specify the city being used in all the requests I'll make to this service, I could pass that in the URL's querystring:

$(document).ready(function () 
 ws = new WebSocket("ws://localhost/WSSample/OrderStatus.svc?city=Regina");

I'm now ready to issue a request to the single method in the service by calling the WebSocket's send method, passing a parameter. However, it's certainly possible that I could get to the line of the code that issues the request before the connection is opened—that will generate an error. To ensure that the connection is open and ready to use, check the WebSocket object's readyState property to see if it's set to the OPEN constant (defined in the WebSocket object).

This code checks to see if the WebSocket is open before calling the service's method passing an Order Id. If the connection isn't open, the code notifies the user:

if (ws.readyState === ws.OPEN)
 alert("Connection to service not yet open.");

It would make sense to put code like this behind the onclick event of a button that the user clicks on after selecting the Order to be monitored. However, if you want to call the service as soon as it's available, you can attach a function to the WebSocket's onopen event, which fires as soon as the connection's open. This code sends the Order Id as soon as the connection's available:

ws.onopen = function () 

When the service sends data to the client, the WebSocket object will raise an onmessage event and the data will be passed to the event. This code attaches a function to process that data to the WebSocket's onmessage event:

wss.onmessage = function (status) 
 $("#orderStatusInfo").append( + "<br/>");

It's probably a good idea to wire up a function to the onmessage event before you call the send method on the WebSocket object. That will ensure you're ready to catch the data from the service before the service starts sending it. If, of course, you don't need any more information from the service, you can simply close the connection using the WebSocket's Close method:

wss.onmessage = function (status) 
 $("#orderStatusInfo").append( + "<br/>");

Hopefully, the author of the service will have written the service so it won't attempt to send data once the receiving connection's closed (I discussed how to check for that in WCF 4.5 in my previous column).

It's also possible that you'll call the service multiple times, for at least two reasons:

  • To change the parameters for the kind of data you're expecting (in my case, to change the order whose status you wish to monitor)
  • To make a second request to be processed in parallel with your first request (i.e., to monitor a second order while still monitoring the first Order), or to cancel processing the first order.

The problem is that, in WCF 4.5 at least, a second call won't be processed while the first call is still executing. So if your first request instantiated a loop that continuously monitored the order's status, your second request won't be accepted. To prevent the first request from blocking any subsequent request, your service will need to spin off process to another thread.

For instance, this code in the method that accepts request calls a method named SendOrderStatus (passing the OrderId) and then exits, freeing up the method for a second request. The SendOrderStatus method, presumably, monitors the order status and sends updates to the client:

Dim t As Threading.Thread
  t = New Threading.Thread(
    New Threading.ThreadStart(Function() SendOrderStatus(OrderId)))
End Sub

If you do have an ongoing process, you'll want to terminate it when the client stops listening for results. The only way to do that, apparently, is to catch the exception raised when you attempt to send data through a closed connection.

In my next column, I'll be finishing this exploration by looking at a simpler way to create a WCF WebSockets service.

About the Author

Peter Vogel is a system architect and principal in PH&V Information Services. PH&V provides full-stack consulting from UX design through object modeling to database design. Peter tweets about his VSM columns with the hashtag #vogelarticles. His blog posts on user experience design can be found at

comments powered by Disqus


  • Uno Platform Ports Windows Calculator to Linux

    Uno Platform has ported the famed Windows Calculator, open sourced last year, to Linux as part of a continuing "proof point" effort to demonstrate the reach of what it describes as the sole UI offering available to target Windows, WebAssembly, iOS, macOS, Android and Linux with single-codebase applications coded in C# and XAML.

  • ASP.NET Core OData 8 Preview Supports .NET 5, but with Breaking Changes

    ASP.NET Core OData, which debuted in July 2018, is out in a v8.0 preview that for the first time supports the upcoming .NET 5 milestone release.

  • VS Code Java Team Details 5 Best Dev Practices

    Microsoft's Visual Studio Code team for Java development added a new Coding Pack for Java installer and detailed best practices for setting up a development environment.

  • Binary Classification Using PyTorch: Defining a Network

    Dr. James McCaffrey of Microsoft Research tackles how to define a network in the second of a series of four articles that present a complete end-to-end production-quality example of binary classification using a PyTorch neural network, including a full Python code sample and data files.

  • Blazor Debugging Boosted in .NET 5 RC 2

    In highlighting updates to ASP.NET Core in the just-launched second and final Release Candidate of .NET 5, Microsoft pointed out better debugging for Blazor, the red-hot project that allows for C# coding of web projects.

Upcoming Events