Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to make Blazor Server SignalR connection use a different URL? #59546

Open
pablosantosluaces opened this issue Dec 18, 2024 · 4 comments
Open
Labels
area-blazor Includes: Blazor, Razor Components Docs This issue tracks updating documentation
Milestone

Comments

@pablosantosluaces
Copy link

My question is: how to configure the endpoint used by signalr in Blazor server?

Scenario

  • I have a Blazor server app running on Azure Container Apps.
  • The app implements 2 things: a REST API and the website itself using Blazor Server.
  • I configured APIM with the custom domain defined there, and the correct SSL Cert.
  • Then I had to configure an API for the REST API (obvious).
  • But then I configured "other" API to send all website traffic too, otherwise the website wouldn't work. I guess this is not the normal way to use APIM but since we only have 1 certificate and we need it to work for the API and the website, I did it there.
  • Everything was working except the websockets connection. Each time I visit our site, I get this:

Error: Failed to start the transport 'WebSockets': Error: WebSocket failed to connect. The connection could not be found on the server, either the endpoint may not be a SignalR endpoint, the connection ID is not present on the server, or there is a proxy blocking WebSockets. If you have multiple servers check that sticky sessions are enabled.

So, probably the solution is to define an extra WebSocket API in APIM and make the SignalR code go through it.

But, in order to achieve it, I need the javascript side of things to point to something like MYSITE/signalr/_blazor?id=xxx intead of wss://MYSITE/_blazor?id=xxxx

How can I achieve this?

There are some random answers here and there, and "probably" this is the way to achieve it:

<script src="~/_framework/blazor.server.js" autostart="false"></script>
<script>
Blazor.start({
        configureSignalR: function (builder) {
            builder.withUrl("/_blazor", {
                
            });
        }
    });
</script>

But it would be good to be able to find a proper example instead of stackoverflowing this.

@javiercn :-)

Extra info

I found some info about how to do it but the docu is not very clear here: https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/startup?view=aspnetcore-9.0 it mentions something, but where is the detailed info of each option?

It does mention this, but where are all the circuit options??

<script src="{BLAZOR SCRIPT}" autostart="false"></script>
<script>
  ...
  Blazor.start({
    ssr: {
      ...
    },
    circuit: {
      ...
    },
    webAssembly: {
      ...
    }
  });
  ...
</script>
@dotnet-issue-labeler dotnet-issue-labeler bot added the area-blazor Includes: Blazor, Razor Components label Dec 18, 2024
@pablosantosluaces
Copy link
Author

how to make your blazor server app start the signalr channel in a different url

  1. Add this to your App.razor (replace the previous line including the blazor.web.js) if you want a "signalr" url
        <script src="_framework/blazor.web.js" autostart="false"></script>
        <script>
            console.log("start invoked");

            Blazor.start({
                circuit: {
                    configureSignalR: builder => builder.withUrl("/signalr")
                },
            });
        </script>
  1. Add this to your Program.cs:

app.MapBlazorHub("/signalr");

Done. Easy. But hard to find the instructions.

@pablosantosluaces
Copy link
Author

How to make your Blazor Server application run in a container app behind APIM

  1. You need to change your signalr url. The default _blazor won't work because APIM doesn't let you "listen" on that route. Just gives an error.

  2. Create a websocket type api and point to you container app url.

  3. Create a HTTP API and point to your container app url too, and follow this instructions to add 2 commands: https://learn.microsoft.com/en-us/azure/azure-signalr/signalr-howto-work-with-apim#configure-apis-when-client-connects-with-websocket-transport

The instructions are good but misleading because they mention "Azure SignalR Service" but they are valid too for a NORMAL app that doesn't use SignalR Service but just normal SignalR.

Also, in my case, I had APIM configured to run the entire website too, but it DID NOT WORK to handle the websocket negotiation... so I had to add yet another HTTP API. In my case I had:

  • HTTP REST API for my REST API (not relevant here) (created from the 'container app' resource). URL is https://www.mywebsite.com/api
  • HTTP REST API for the entire website. URL https://www.mywebsite.com. I had to add some policies to pass some extra headers for auth0 to work and more.
  • HTTP REST API just to handle signalr negotiate. The previous didn't work. API URL prefix: signalr/negotiate
  • WSS API. API URL prefix: signalr

With these last two negotiation worked!

@javiercn
Copy link
Member

@pablosantosluaces thanks for contacting us.

Your solution is correct as for configuring the Blazor connection endpoint URL.

As for the APIM solution, the approach looks ok at first glance.

@guardrex can you make sure that the docs are up to date to reflect #59546 (comment)

@javiercn javiercn added the Docs This issue tracks updating documentation label Dec 19, 2024
@javiercn javiercn added this to the Backlog milestone Dec 19, 2024
@pablosantosluaces
Copy link
Author

Thanks :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components Docs This issue tracks updating documentation
Projects
None yet
Development

No branches or pull requests

2 participants