In my previous post I mentioned a limitation when combining SignalR and TypeScript, how we couldn’t take advantage of the client interface definition, that we created for TypeScript’s use, to also get Intellisense when coding on the server’s C# side. I suggested that perhaps there was a way to do it with conditional compilation flags, and today I thought I’d spend some time figuring it out…

…which didn’t take very long at all. What I now have in each of my Hubs is code like the following:

#if Debug
public dynamic Others { get { return Clients.Others; } }
public dynamic All { get { return Clients.All; } }
public dynamic Self { get { return Clients.Caller ; } }
#else
public IChatHubClient Others { get { return Clients.Others as IChatHubClient; } }
public IChatHubClient All { get { return Clients.All as IChatHubClient; } }
public IChatHubClient Self { get { return Clients.Caller as IChatHubClient; } }
#endif

This now lets me use a line such as

All.addNewMessageToPage(msg);

in the server’s Send() function, and I get Intellisense providing addNewMessageToPage() as a suggestion, and I get a pre-compile-time check that the msg parameter is correct.

This works because at editing time, Debug is not defined, so I get the IChatHubClient casting of the different dynamic objects that I wish to use Intellisense on and have the pre-compiler check against. When compiled, however, Debug is defined, and the proper dynamic objects are used, which allows the SignalR library to happily send the requests to the client-side functions I’ve claimed are there.

Once I’m ready to move this to production, I’ll have to add an additional Release or something similar, to ensure the code still compiles correctly.

Oh, and for those reading this that have no interest in using TypeScript with SignalR (shame on you!), you can still use this trick of defining the client-side interface and casting it; you just won’t be using the interface to also generate TypeScript definition files.

Advertisements