Saturday, 6 July 2013

C# client for Server Side Events (EventSource)

Examples of one way streaming from server to client can be found on the web but it’s pretty much always JavaScript clients.  Here is a working example using the .NET stack, with WebAPI as the server and a C# console application as the client.

Download and run this WebAPI chat application which emits Server Side Events:

I then open Visual Studio running as admin, update the code to use IIS with my machine name (Zeus) and a virtual directory, clicking the create virtual directory button, so I can track requests using Fiddler:


Then update the JavaScript within the app to use the same path:


The create a Console application, using NUGET add Json.NET and paste this code in:

using System;
using System.IO;
using System.Net;
using System.Text;
using Newtonsoft.Json;

namespace ConsoleApplication2
class Program
static void Main(string[] args)
new WebClientWrapper();

public class WebClientWrapper
WebClient wc { get; set; }

public WebClientWrapper()

// When SSE (Server side event) occurs this fires
private void OnOpenReadCompleted(object sender, OpenReadCompletedEventArgs args)
using (var streamReader = new StreamReader(args.Result, Encoding.UTF8))
var cometPayload = streamReader.ReadLine();
var jsonPayload = cometPayload.Substring(5);
var message = JsonConvert.DeserializeObject<Message>(jsonPayload);
Console.WriteLine("Message received: {0} {1} {2}", message.dt, message.username, message.text);

private void InitialiseWebClient()
wc = new WebClient();
wc.OpenReadAsync(new Uri("http://zeus/chatapp/api/chat/"));
wc.OpenReadCompleted += OnOpenReadCompleted;

public class Message
public string username { get; set; }
public string text { get; set; }
public string dt { get; set; }

You’ll need to update the code for your machine name.

Now run Fiddler, the WebAPI project and the console app and add a message in the chat window:


In Fiddler, select the request your console just made and select Raw, you’ll see nothing.  Now right click and select COMETPeek and you’ll see the payload that was streamed.


1 comment:

  1. I have set up my iis and fiddler and when i try to fire up my console app i get the following exception on the console app and it blows up

    '\\chi-file-01b\users\dpinto\my documents\visual studio 2013\Projects\ConsoleApp
    CMD.EXE was started with the above path as the current directory.
    UNC paths are not supported. Defaulting to Windows directory.

    Unhandled Exception: System.Reflection.TargetInvocationException: An exception o
    ccurred during the operation, making the result invalid. Check InnerException f
    or exception details. ---> System.Net.WebException: An exception occurred during
    a WebClient request. ---> System.Configuration.ConfigurationErrorsException: Er
    ror creating the Web Proxy specified in the '' configurat
    ion section. ---> System.Net.Sockets.SocketException: An invalid argument was su
    at System.Net.SafeCloseSocketAndEvent.CreateWSASocketWithEvent(AddressFamily
    addressFamily, SocketType socketType, ProtocolType protocolType, Boolean autoRes
    et, Boolean signaled)
    at System.Net.NetworkAddressChangePolled..ctor()
    at System.Net.AutoWebProxyScriptEngine.AutoDetector.Initialize()
    at System.Net.AutoWebProxyScriptEngine.AutoDetector.get_CurrentAutoDetector()

    at System.Net.AutoWebProxyScriptEngine..ctor(WebProxy proxy, Boolean useRegis
    at System.Net.WebProxy.UnsafeUpdateFromRegistry()
    at System.Net.WebProxy..ctor(Boolean enableAutoproxy)
    at System.Net.Configuration.DefaultProxySectionInternal..ctor(DefaultProxySec
    tion section)
    at System.Net.Configuration.DefaultProxySectionInternal.GetSection()
    --- End of inner exception stack trace ---
    at System.Net.Configuration.DefaultProxySectionInternal.GetSection()
    at System.Net.WebRequest.get_InternalDefaultWebProxy()
    at System.Net.HttpWebRequest..ctor(Uri uri, ServicePoint servicePoint)
    at System.Net.HttpRequestCreator.Create(Uri Uri)
    at System.Net.WebRequest.Create(Uri requestUri, Boolean useUriBase)
    at System.Net.WebRequest.Create(Uri requestUri)
    at System.Net.WebClient.GetWebRequest(Uri address)
    at System.Net.WebClient.OpenReadAsync(Uri address, Object userToken)
    --- End of inner exception stack trace ---
    --- End of inner exception stack trace ---
    at System.ComponentModel.AsyncCompletedEventArgs.RaiseExceptionIfNecessary()
    at System.Net.OpenReadCompletedEventArgs.get_Result()
    at ConsoleApplication2.WebClientWrapper.OnOpenReadCompleted(Object sender, Op
    enReadCompletedEventArgs args) in \\chi-file-01b\users\dpinto\My Documents\Visua
    l Studio 2013\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 3
    at System.Net.WebClient.OnOpenReadCompleted(OpenReadCompletedEventArgs e)
    at System.Net.WebClient.OpenReadOperationCompleted(Object arg)
    at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object sta
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionCo
    ntext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, C
    ontextCallback callback, Object state, Boolean preserveSyncCtx)
    at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWor
    at System.Threading.ThreadPoolWorkQueue.Dispatch()
    at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
    Press any key to continue . . .