Skip to main content

SignalR not connecting? Things to check


SignalR is a websocket library for .NET. During setup and local development there are a number of issues you may encounter. In this post I’ll explain how to fix these.

I will assume you are using ASP.NET core, version 2.2 or later. And your client is just plain old vanilla JavaScript.

Obviously your first step should be reproducing your issue with new empty projects, where you can be sure nothing else is interfering. Beyond that, here are a few tips:

Client Scripts Updated

To use SignalR in JavaScript you should be have the official client-side library from Microsoft. This is usually a single file called signalr.js or signalr.min.js (the minified version). You can find basic HTML/JS example use here to check you are using it correctly.

If you have got the client scripts from a non-official source, or there is a chance they might be out-of-date, make sure you replace them with the latest version. The best way is to obtain the latest version is to read Microsofts official documentation. It explains how to obtain the scripts using Visual Studio, or an even simpler option … use a CDN.

HTTPS client with HTTP server - ‘Mixed Content’

An obvious beginner mistake. But, we’ve all got to start somewhere right?

Don’t access your client web app using ‘https’ and your SignalR server on ‘http’. Web browsers don’t like it. If you’re web browser fetches a web page securely, it expects all the linked content, and javascript web requests to be done over SSL too.

If you do this, your web brower should tell you something about the site not being secure. And it will likely block all of these requests, like those trying to establish a SignalR connection.

This is generally referred to as HTTPS mixed content.

The fix is simple. Either downgrade your website to use http, or upgrade your server to use https.

Set the correct URLs

Again … obvious. Make sure your script has the correct URL of the SignalR server assigned.
Pay particular attention to whether it is ‘http’ or ‘https’, the path is the same as the route of the Hub in your ASP.NET Core app.

If you are using localhost, make sure you assign the correct port! You’re project settings of your ASP.NET core app will show this. I recommend using http when tesing locally, as development SSL certificates can be a nuisance.

It should look something like this:

var connection = new signalR.HubConnectionBuilder().withUrl("http://localhost:63205/myhub").build();

A Websever for your Website

Opening your website by literally opening a index.html file in your web browser is not a good idea. Most web browsers will block cross-origin requests when you do this, and normally log it as a CORS error.

If you are doing this, you’re address bar will display something like:

file:///C:/Users/.../index.html

To avoid this, you need to start a local webserver which will serve your files. Then access it using localhost or a local ip address such as 127.0.0.1 or something starting with 192 or 172. And you’ll usually have to provide a port number too like 8080.

http://127.0.0.1:8080/

How do you do this? My prefered method is to use node.js which you can install here. Then open a terminal and use the following command to install the http-server package:

npm install --global http-server

And from there it is simple. Every time your want to start a webserver, open a terminal to the directory containing your index.html, javascript files and whatever else. Simply type http-server. Then it will give you the address such as 127.0.0.1:8080 which you can open in a web browser to access your website.

Now take note of the address serving your website, you’ll need it to configure CORS correctly …

CORS

CORS can be a nightmare for web developers testing their work locally. But, it is a necessary evil.

You can check for errors these using the F12 developer tools in your web browser. Any red error message in the console which mentions CORS, means you haven’t configured it correctly. But first to explain what it is …

Suppose you are on example.com and the website wants to fetch something from another domain like jam-es.com. If that was allowed, anyone who visits example.com will be pinging jam-es.com. If example.com is your site, and it’s quite popular, you could easily get your visitors machines to flood jam-es.com with requests and perform a DDoS attack. For this reason, web browser block visitors of one domain (example.com) from sending requests to another domain (jam-es.com), unless jam-es.com explicitly says it allows requests from visitors of example.com.

This is the exact scenaro you may have. You are visiting your web app on one domain example.com but it is trying to send requests to a different domain, the domain of your SignalR server jam-es.com (or even just a different subdomain like signalr.example.com). Those requests will be blocked unless you configure CORS correctly by ensuring OPTIONS requests to jam-es.com return a certain HTTP response header.

This header has the name Access-Control-Allow-Origin and it must be returned by your SignalR server. This only applies when your client sends requests with an Origin header (to tell the server which domain the visitor making the request is coming from), which all web browsers include by default (and it is hard to disable).

The Access-Control-Allow-Origin header may return 3 different values. Either the wildcard * to allow all domains, or null (which you should never use), or it should be set to the domain the vistor’s is making the request from like example.com.

Note: With SignalR you cannot use *, because SignalR requires the use of credentials, and requests using * with credentials will all be blocked by your web browser too 🙄.

Therefore, we need to change our ASP.NET Core SignalR server to return this header with the value set to the domain the requests are coming from. If you are testing locally and read the last section this will be a local IP address with a port like 127.0.0.1:8080, otherwise it is the domain of your website example.com.

Within Startup.cs inside ConfigureServices add the following line:

services.AddCors();

And within Configure add:

app.UseCors(builder =>
{
    builder.WithOrigins("http://127.0.0.1:8080", "https://example.com")
        .AllowAnyHeader()
        .WithMethods("GET", "POST")
        .AllowCredentials();
});

Notice here, we’ve provided two allowed origins, one which we can use for development, and the other for production. But the method will accept as many as you like, or even just one. Make sure you include the ‘http’ or ‘https’ correctly.

Now build and run your webserver, and hopefully you will not get any more issues with CORS … but you might …

Deployment issues … CORS again?

By this point, you should be able to get things working locally. But you might still have issues when deployed to your site example.com (when using it as an origin above).

You’re going to have to go through all the settings on your server or cloud dashboard, until you find what is set wrong.

For example, if using a server or cloud VM, make sure your firewall is open to all sources on ports 80 and 443.

But, for Azure Web App users … I recommend you check this first. Navigate to your web app (App Service resource) in the Azure Portal and look for the section called ‘CORS’ in the left-hand menu. If enabled this will enable CORS at an App Service level and override everything you set in the set above … and break your SignalR connections. So make sure this is DISABLED, i.e. remove anything from the ‘Allowed Origins’ list, especially remove the wildcard * if it appears.

Thanks for Reading

Hopefully all your issues are fixed now … or at least those relating to SignalR conenctions 🙂

Comments

Popular posts from this blog

Terminals in Sublime Text 3

TL;DR - Need a quick answer on how to create terminals in Sublime Text 3? Scroll down and watch the video or read the instructions below it. A while ago I started a series on YouTube of 'Sublime Text Tips'. Sublime Text 3 is one the best code editors currently in existence (fact), but most people just install it an use it without realising how it can be customized and extended to meet your needs. My aim was to release a series of videos explaining some of these widely unknown capabilities. I got as far as the third video and then got distracted with other things 😅 But recently I noticed the 3rd video I made has been increasing in popularity. For at least 6 months it sat at less than 200 views, and over the course of the last 2 months it has shot up to 850 (at the time of writing). Perhaps it's coincidence, or perhaps YouTube's algorithms have changed. Either way, there seem to be people who want this information. The video explains how to set up termin...

Generating a MSI Installer for a WPF Application

This post serves as a tutorial for creating a MSI installer for your WPF Applications in Visual Studio. For this we use WiX (recommended by Microsoft). Prerequisites I assume you already have a Visual Studio solution containing a WPF Project. And I assume you have some experience with Visual Studio and XML. You do not need any prior knowledge of WiX. Step 1: Install Wix We are going to need WiX to generate our MSI. If you don't already have Wix installed, go ahead and download it from here . You'll be redirected to the relevant GitHub releases page where you can download the .exe file to install WiX.

Best Packages for Sublime Text 3 (Excluding Themes)

Sublime Text 3 is pretty good out-of-the-box but reaches a whole new level when you install some of the great packages on offer. Below I'll list my favourite packages for Sublime Text. These are all packages which will enhance your productivity across all languages, so no themes or language-specific packages will be listed here.