SignalR metadata for Asp.Net Core 2.1

Hello and welcome šŸ™‚

This will be a short post which will tie in with the next post about branching authentication in asp.net core using middleware.

The problem

Recently I encountered a situation in which I needed to pass to a SignalR hub additional data with every request, kinda like environment metadata from external systems. In my case, it was the username from an external system to correlate it.

Of course the obvious answer would have been that every time I invoked a method on the hub, to also pass along the metadata as a parameter, but that would become cumbersome since this was related to users, so it needed to be in each and every request, cookies were off the table since the requests would be coming from a different domain, and with web sockets involved, it’s not like we can build the request each time like for ajax calls.

I started looking into additional ways to send information to the hub in such a way that it would always be present from that caller, and also not mess up my method calls.

Some of you might know that the current approach to connect to a SignalR hub now is by using the following snippet of code in javascript:

const connection = new signalR.HubConnectionBuilder().withUrl("/hub").build(); // this builds the connection for the hub

connection.on("hubMethod", (messages) => { // this is a handler for when the hub reaches the client on the "hubMethod" client endpoint.
alert(messages);
});

connection.start().catch(err => console.error(err.toString())); // here we just start the connection and log out any errors that might occur.

The solution

In my case, I wanted to add a username associated with each call so that I can handle it in some custom middleware (which has access to the HttpContext which holds information about the current request). The change for that was actually so minor that it could be easily overlooked, so what I changed to that snippet of code was the following:

const username = "Vlad";
const connection = new signalR.HubConnectionBuilder().withUrl(`/hub?UserName=${username}`).build(); // this builds the connection for the hub

connection.on("hubMethod", (messages) => { // this is a handler for when the hub reaches the client on the "hubMethod" client endpoint.
alert(messages);
});

connection.start().catch(err => console.error(err.toString())); // here we just start the connection and log out any errors that might occur.

With this change, if you were to have a look at the request coming in, it will always have that query string attached, and that will be present for all and any future calls from that particular client to the hub.

But how can I use that in the hub?

In this particular case there was no need to access the HttpContext from the hub since it was gonna get used in the middleware before it reaches the hub, but if you have a look at the Context property of a SignalR Hub, you will notice that context it isn’t an HttpContext so we will need an extra step so that we can access the metadata in our hub methods as well.

To get the HttpContext inside of a Hub method all we need to do is add the following line to the method:

HttpContext httpContext = Context.Features.Get().HttpContext;

Pro tip

If your metadata is getting too big (which it really shouldn’t) please keep in mind that query strings have a limit on the number of characters that can be sent, so in those cases it might be worthwhile looking into compressing that string parameter client side and decompressing it server side (maybe we will cover that in a future post šŸ˜‰ ).

Cheers and happy coding,
Vlad V.

Advertisements

One thought on “SignalR metadata for Asp.Net Core 2.1

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s