Click here to Skip to main content
Click here to Skip to main content

What's new in WCF 4.5? WebSocket support (Part 1 of 2)

By , 2 Mar 2012
Rate this:
Please Sign up or sign in to vote.

This is the 11th post in the WCF 4.5 series. The previous post was about the new UDP transport support, and this new post is also about new transports – the WebSocket transport.

This post is part 1 of 2. This post will be about the WebSocket support between .NET apps using WCF (SOAP-based), and the next post will be about using WebSockets between browsers and WCF (non-SOAP).

Previous posts:

1. What’s new in WCF 4.5? let’s start with WCF configuration

2. What’s new in WCF 4.5? a single WSDL file

3. What’s new in WCF 4.5? Configuration tooltips and intellisense in config files

4. What’s new in WCF 4.5? Configuration validations

5. What’s new in WCF 4.5? Multiple authentication support on a single endpoint in IIS

6. What’s new in WCF 4.5? Automatic HTTPS endpoint for IIS

7. What’s new in WCF 4.5? BasicHttpsBinding

8. What’s new in WCF 4.5? Changed default for ASP.NET compatibility mode

9. What’s new in WCF 4.5? Improved streaming in IIS hosting

10. What’s new in WCF 4.5? UDP transport support

A (very) short introduction to WebSockets – WebSocket is a bi-directional (two-way), full-duplex channel. WebSocket channels start as normal HTTP channels, and then use handshakes to upgrade the channel to WebSocket, allowing two-way TCP communication between client and server, thus overcoming several limitations enforced by firewalls. In order not to repeat all that is already written about WebSockets, I suggest you check the following websites:

http://en.wikipedia.org/wiki/WebSocket

http://websocket.org/

https://datatracker.ietf.org/doc/rfc6455/

Note: This post was written according to the WebSocket support of WCF 4.5 with .NET 4.5 Beta and Visual Studio 11 Beta. If you are still using the Developer Preview version, you might see some different configuration sections and different behavior of the “Add Service Reference” feature.

The support of WebSocket in WCF 4.5 is achieved through the new NetHttpBinding. The NetHttpBinding was first introduced in the WCF 4 samples as a custom binding that uses binary-encoded SOAP messages over HTTP(S). The NetHttpBinding in WCF 4.5 is an improved binding that uses binary-encoded SOAP messages over HTTP(S) or WebSocket transports. The NetHttpBinding can be used in any of the following ways:

  1. Request-Response over HTTP. This mode does not use WebSockets, but rather a simple HTTP/HTTPS channel with binary-encoded SOAP messages.
    This mode is the default mode when using the binding without a duplex contract.
  2. Duplex over WebSocket. This mode uses WebSockets, and allows two-way communication between client and service.
    This mode is automatically used when you declare your service contract with a callback contract (duplex).
  3. Request-Response over WebSocket. This mode uses WebSockets, but it does not take advantage of the two-way communication support of the channel (since we still use the request-response pattern).
    This mode is used when doing one of the following:
    1. Changing the SessionMode of the contract to Required. The binding will upgrade automatically from HTTP to WebSocket, since HTTP is not sessionful and WebSocket is.
    2. Manually forcing WebSocket by changing the binding configuration and setting the WebSocket transport usage to Always.

Since WebSocket is sessionful, you automatically get session support in your service, if you haven’t changed the instance context mode from the default PerSession setting. If you’ve ever needed a sessionful HTTP channel and had to use WsHttpBinding with WS-ReliableMessaging, you now have another option which doesn’t require passing extra WS-RM messages.

NetHttpBinding with WebSocket can in fact replace the use of WsDualHttpBinding, since WebSocket provides a duplex channel which also supports sessions – this is better than WsDualHttpBinding which uses two channels, and require the use of WS-ReliableMessaging for session management.

All three modes of the binding are non-interoperable, because they use binary-encoded SOAP messages which is a proprietary Microsoft encoding technique. If you want to learn more about binary encoding, I suggest you read Nicholas Allen’s posts on the subject. However, this does not mean we cannot use WebSockets as an interoperable transport with text-based SOAP messages – we can change the binding configuration to use text instead of binary, thus making in interoperable, as shown later on.

To demonstrate the usage of NetHttpBinding, I’ve created a simple duplex contract:

[ServiceContract(CallbackContract=typeof(IDuplexCallbackContract))]
public interface IDuplexContract
{
    [OperationContract]
    string SayHelloDuplex(string name);
}

[ServiceContract]
public interface IDuplexCallbackContract
{
    [OperationContract]
    void SayingHello(string message);
}
And a service that implements the contract:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class WebSocketSampleService : IRegularContract, IDuplexContract
{
    public string SayHelloDuplex(string name)
    {
        OperationContext.Current.
            GetCallbackChannel<IDuplexCallbackContract>().
            SayingHello("Hello " + name + " by WebSockets");

        return "Hello " + name;
    }
}

The endpoint configuration is quite simple:

<endpoint address="http://localhost:8083"
          binding="netHttpBinding"
          contract="Contracts.IDuplexContract"/>

Note: It appear that the WCF Service Configuration Editor doesn’t recognize the NetHttpBinding’s WebSocket configuration, so you’ll need to use Visual Studio’s XML editor (the binding configuration is supported from VS11 Beta).

And as for the client-side code, just add a service reference and call the service:

Services.IDuplexContract duplexProxy;
Console.WriteLine("Press enter when service is ready");
Console.ReadLine();

// Use the generated proxy class
duplexProxy = new Services.DuplexContractClient(
    callbackContext,
    "DuplexContract");
Console.WriteLine("Calling the duplex contract:");
Console.WriteLine(duplexProxy.SayHelloDuplex("ido"));

// Or use a DuplexChannelFactory
DuplexChannelFactory<Services.IDuplexContract> dchf =
    new DuplexChannelFactory<Services.IDuplexContract>(
        callbackContext,
        new NetHttpBinding(),<br />        new EndpointAddress("http://localhost:8083/"));
duplexProxy = dchf.CreateChannel();
Console.WriteLine("Calling the duplex contract using text encoded messages:");
Console.WriteLine(duplexProxy.SayHelloDuplex("ido"));

Note: When specifying the endpoint address in the service, you need to use the http:// scheme, but on the client-side you can use either http:// or ws://. When generating a service reference, the client configuration will use the ws:// scheme.

Note: If your service endpoint uses NetHttpBinding but you contract is a non-duplex service contract (without a callback contract), you can still use NetHttpBinding, but the channel will be HTTP and not WebSockets – in this case the generated client configuration will create a custom binding instead of NetHttpBinding. The custom binding is a perfect match of the NetHttpBinding so things will still work, but it may be a bit confusing the first time you see it. I hope this will be resolved in the RTM version of VS 11.

When you add a service reference to the service, the client side configuration will be generated with a custom binding instead of the NetHttpBinding - you can either leave it as-is, or remove the custom binding and rewrite the configuration to use the NetHttpBinding (of course you might need to do it again when you update the service reference).

It is also quite easy to define a new service endpoint which uses the NetHttpBinding with text-based SOAP messages instead of binary:

<service name="Host.WebSocketSampleService">
    <endpoint address="http://localhost:8084"
              binding="netHttpBinding"
              bindingConfiguration="TextOverWebSockets"
              contract="Contracts.IDuplexContract"/>
</service>
<bindings>
  <netHttpBinding>
    <binding name="TextOverWebSockets" messageEncoding="Text"/>
  </netHttpBinding>
</bindings>

So as you can see, we have the ability to use both binary and text, but how can we be sure it actually passes text instead of binary? for that we need a network sniffer that can show us the WebSocket messages. You can use Wireshark or any other TCP sniffer to check that, however I always found those sniffers to be a bit hard to manage, especially for localhost communication. Luckily for us, we can use Fiddler, the famous HTTP sniffer, which now supports WebSocket messages (although only for watching).

This is how the binary message looks like when sent over WebSockets:

image

And this is how the text message looks like:

image

And this is the HTTP connection upgrade request:

image

(notice the GET request for WebSocket upgrade, and the corresponding HTTP 101 – Switching Protocols response)

If you want to use WebSockets for a simple Request-Response contract, you can also do that, but you’ll need to set the binding configuration of your endpoint to require WebSocket communication:

<bindings>
    <netHttpBinding>
        <binding name="ReqResWithWebSockets">
             <webSocketSettings transportUsage="Always"/>
        </binding>
    </netHttpBinding>      
</bindings>

You can download the sample code from my SkyDrive which demonstrates all of the above including duplex, request-response, sessions, forcing WebSockets, and text encoded messages.

When considering the use of WebSocket via NetHttpBinding for duplex communication vs. WsDualHttpBinding and NetTcpBinding, the benefits of NetHttpBindings are:

  1. Like NetTcp it requires one channel instead of two, as in the case of WsDualHttp.
  2. Like NetTcp it has a sessionful channel, unlike WsDualHttp which requires the use of WS-ReliableMessaging.
  3. Like NetTcp, it uses binary encoding which reduces the message size, unlike the text encoding of WsDualHttp.
  4. Unlike NetTcp, it can overcome some firewall restrictions that prohibit TCP communication.

As we’ve seen so far, the WebSocket support in WCF 4.5 uses SOAP-based messages. In the next post I will cover how to use WebSockets in WCF 4.5 to communicate with non-SOAP clients, such as web browsers, using simple text over WebSockets.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Ido Flatow
Architect Sela Group
Israel Israel
Web developer since 1997. I'm a senior architect at Sela Group in Israel. I'm a consultant, trainer (Microsoft MCT), and a speaker in conferences worldwide.
My main fields are WCF, ASP.NET, Windows Azure, IIS, Entity Framework, and Silverlight.
Follow on   Twitter

Comments and Discussions

 
QuestionDid you ever post your second article? Pinmemberjasdflkjasdfj29-Oct-12 5:41 
AnswerRe: Did you ever post your second article? PinmemberIdo Flatow19-Nov-12 2:31 
QuestionVery useful - one question PinmemberMR_SAM_PIPER17-Apr-12 19:51 
GeneralMy vote of 5 Pinmemberchristoph braendle3-Mar-12 1:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140415.2 | Last Updated 2 Mar 2012
Article Copyright 2012 by Ido Flatow
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid