SignalR Core - NOT POSSIBLE
Unfortunately this is not possible anymore in the new 'Core' version of SignalR
https://github.com/aspnet/SignalR/issues/456
https://github.com/aspnet/SignalR/issues/955
Notes: Issues with iOS and self signed certificates
On iOS there's a limit of FOUR connections per server.
Now there isn't this limit for websockets (I think it may be 32 but not sure). However I am using a self signed certificate which has all kinds of issues in Safari - so it actually drops down to long polling (and it's not obvious it's done so).
So I ended up with these connections:
- 1 - Angular / Webpack hot reload socket
- 2 - Web API calls
- 3 - Hub number one
- 4 - Hub number two
- 5 - #&#&#$&#$&
So if I had ONLY three hubs the whole Safari page would lock up with a blue bar. Even Web API calls got blocked.
Note: With HTTP/2 this limit is gone but you're probably better off limiting yourself to one hub especially if you're using hot reload. Plus setting up HTTP/2 in development isn't necessarily a trivial task.
So how to fix?
First (temporarily) set your hub to only accept websockets. This will give you an error in Safari (make sure errors are being caught and shown in an alert dialog).
routes.MapHub<SignalRHub>("/rt", options =>
{
// when run in debug mode only WebSockets are allowed
if (Debugger.IsAttached) {
options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets;
}
});
Now you'll be able to confirm the fix - run in debug mode, or remove the 'if'.
The problem with iOS is even if you accept a self signed certificate for https traffic - and get a nice little 'lock' symbol in the browser - it doesn't apply to the wss: protocol. So connections cannot be upgraded to wss, which is why they block at the max of 4.
Solution #1
If you can get everything down to one hub it's just easier :-)
I also realized that multiple hubs complicates reconnect logic if the connection is lost. One hub just makes this easier. If you're not careful you'll end up showing 3 dialog boxes saying 'Connection lost. Retry?' I'm switching to a single hub just because of this.
While I hate mixing everything, partial classes help and I personally don't have many SignalR methods anyway.
Solution #2
This is only relevant to debugging, and assumes you're using a https cert which you self-signed.
Use instead something like letsencrypt - or Cloudflare's argo tunnel to get a publically trusted cert. This will be fully trusted by Safari, so your connections will get upgraded to real web sockets.
Solution #3
Create a self signed ROOT certificate (CA) and then generate SSL certificates with the domain name from it.
This was trickier than I imagined. In the end it turned out I was missing Subject Type=CA
in my root cert - which iOS requires. Without this 'extension' it will install your root the certificate as a profile, but won't allow you to select it for SSL.
Once you have the root cert installed Safari will work with websockets just fine.
Solution #4
Use http only. This wasn't an option for me because I use certain APIs like Facebook / Google / Payment and they require https.
Notes
- Important: Now consider production. Realize that websockets may be unavailable for various reasons, so if you have 4 hubs that are connected on iOS this can still cause blocking. You're living dangerously.
Better to use one hub in the first place. BUT also best to get your cert installed properly so iOS will work with websockets.
How to create and install X.509 self signed certificates in Windows 10 without user interaction?