dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.44k stars 10.02k forks source link

MapBlazorHub configuration in NET8 throws a `The request matched multiple endpoints` exception #51698

Open shrayasr opened 1 year ago

shrayasr commented 1 year ago

Is there an existing issue for this?

Describe the bug

We are working on migrating our blazor server application from NET6 to NET8 (to solve some auth issues we were having) and the guide advised this of us:

- app.MapBlazorHub();
+ app.MapRazorComponents<App>()
+   .AddInteractiveServerRenderMode()

And we didn't know where to move the endpoint configuration to, which was previously being done in MapBlazorHub. Our previous call looked like this:

endpoints.MapBlazorHub(config =>
{
    config.CloseOnAuthenticationExpiration = true;
});

This was clarified by @guardrex in https://github.com/dotnet/AspNetCore.Docs/issues/30843 where it was asked for us to place the MapBlazorHub call after the call to MapRazorComponents ... AddInteractiveServerRenderMode block. Which we did. The effective new code looks like this:

app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();

app.MapBlazorHub(config =>
{
    config.CloseOnAuthenticationExpiration = true;
});

However, after doing this and running our project, we got the following exception:

Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: The request matched multiple endpoints. Matches: Blazor initializers

And blazor doesn't seem to boot up on the browser.

Expected Behavior

Server should close the connection once the authentication expiry period is elapsed. This used to happen in NET6.

Steps To Reproduce

We have made a simple reproduction of this and the same is up at: https://github.com/kalai-logicsoft/BlazorNet8AuthTest

Exceptions (if any)

Console

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://localhost:5191/_blazor/initializers - - -
dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1001]
      2 candidate(s) found for the request path '/_blazor/initializers'
dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1005]
      Endpoint 'Blazor initializers' with route pattern '/_blazor/initializers/' is valid for the request path '/_blazor/initializers'
dbug: Microsoft.AspNetCore.Routing.Matching.DfaMatcher[1005]
      Endpoint '(null)' with route pattern '/_blazor/initializers/' is valid for the request path '/_blazor/initializers'
dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[9]
      Connection id "0HMUMNLG9R88S" completed keep alive response.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 GET http://localhost:5191/_vs/browserLink - 200 - text/javascript;+charset=UTF-8 111.2111ms
fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
      Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: The request matched multiple endpoints. Matches:

      Blazor initializers

         at Microsoft.AspNetCore.Routing.Matching.DefaultEndpointSelector.ReportAmbiguity(Span`1 candidateState)
         at Microsoft.AspNetCore.Routing.Matching.DefaultEndpointSelector.ProcessFinalCandidates(HttpContext httpContext, Span`1 candidateState)
         at Microsoft.AspNetCore.Routing.Matching.DefaultEndpointSelector.Select(HttpContext httpContext, Span`1 candidateState)
         at Microsoft.AspNetCore.Routing.Matching.DfaMatcher.MatchAsync(HttpContext httpContext)
         at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext)
         at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
dbug: Microsoft.AspNetCore.Server.Kestrel.Connections[9]
      Connection id "0HMUMNLG9R88R" completed keep alive response.
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished HTTP/1.1 GET http://localhost:5191/_blazor/initializers - 500 - text/plain;+charset=utf-8 53.8392ms

Browser

GET http://localhost:5191/_blazor/initializers 500 (Internal Server Error)
(anonymous) @ blazor.web.js:1
(anonymous) @ blazor.web.js:1
startCircutIfNotStarted @ blazor.web.js:1
resolveRendererIdForDescriptor @ blazor.web.js:1
determinePendingOperation @ blazor.web.js:1
refreshRootComponents @ blazor.web.js:1
(anonymous) @ blazor.web.js:1
setTimeout (async)
rootComponentsMayRequireRefresh @ blazor.web.js:1
onDocumentUpdated @ blazor.web.js:1
Ds @ blazor.web.js:1
VM69:1  Uncaught (in promise) SyntaxError: Unexpected token 'M', "Microsoft."... is not valid JSON
await (async)
startCircutIfNotStarted @ blazor.web.js:1
resolveRendererIdForDescriptor @ blazor.web.js:1
determinePendingOperation @ blazor.web.js:1
refreshRootComponents @ blazor.web.js:1
(anonymous) @ blazor.web.js:1
setTimeout (async)
rootComponentsMayRequireRefresh @ blazor.web.js:1
onDocumentUpdated @ blazor.web.js:1
Ds @ blazor.web.js:1
aspnetcore-browser-refresh.js:260  WebSocket connection to 'wss://localhost:44332/BlazorNet8AuthTest/' failed: 
(anonymous) @ aspnetcore-browser-refresh.js:260
getWebSocket @ aspnetcore-browser-refresh.js:257
(anonymous) @ aspnetcore-browser-refresh.js:16
aspnetcore-browser-refresh.js:19 WebSocket failed to connect.

.NET Version

8.0.100-rc.2.23502.2

Anything else?

dotnet --info

.NET SDK:
Version:   8.0.100-rc.2.23502.2
Commit:    0abacfc2b6

Runtime Environment:
OS Name:     Windows
OS Version:  10.0.22621
OS Platform: Windows
RID:         win-x64
Base Path:   C:\Program Files\dotnet\sdk\8.0.100-rc.2.23502.2\

.NET workloads installed:
There are no installed workloads to display.

Host:
  Version:      8.0.0-rc.2.23479.6
  Architecture: x64
  Commit:       0b25e38ad3

.NET SDKs installed:
  2.1.526 [C:\Program Files\dotnet\sdk]
  2.2.110 [C:\Program Files\dotnet\sdk]
  2.2.207 [C:\Program Files\dotnet\sdk]
  3.1.426 [C:\Program Files\dotnet\sdk]
  5.0.103 [C:\Program Files\dotnet\sdk]
  5.0.408 [C:\Program Files\dotnet\sdk]
  5.0.416 [C:\Program Files\dotnet\sdk]
  6.0.319 [C:\Program Files\dotnet\sdk]
  7.0.310 [C:\Program Files\dotnet\sdk]
  8.0.100-rc.2.23502.2 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.All 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.23 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.24 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.12 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.13 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.0-rc.2.23480.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 1.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.23 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.24 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.12 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.13 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.0-rc.2.23479.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.32 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.17 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.12 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.23 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.24 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 7.0.12 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 7.0.13 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 8.0.0-rc.2.23479.10 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
  arm64 [C:\Program Files\dotnet]
    registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\arm64\InstallLocation]
  x86   [C:\Program Files (x86)\dotnet]
    registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
  Not set

global.json file:
  Not found

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download
guardrex commented 1 year ago

Thanks @shrayasr!

I'm 👂 for PU guidance on Blazor hub options for BWA apps. Our 8.0 section is at ...

https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/signalr?view=aspnetcore-8.0#blazor-hub-options

I'll fix that up immediately upon hearing how those properties are set in the BWA world.

guardrex commented 11 months ago

@mkArtakMSFT ... A new docs issue arrived related to hub config. I was able to address part of the problem raised.

On https://github.com/dotnet/AspNetCore.Docs/issues/31113, the primary ask is about the 8.0-era replacement for app.MapBlazorHub().RequireAuthorization(...), which I believe is app.MapRazorComponents<App>().RequireAuthorization(...). I'm making that update now on https://github.com/dotnet/AspNetCore.Docs/pull/31114.

Earlier, I addressed the server-side circuit handler options. I think the guidance at ...

https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/signalr?view=aspnetcore-8.0#server-side-circuit-handler-options

... is good 👍 (but a PU review of it is welcome).

However, the ask is also about the Blazor hub config guidance at ...

https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/signalr?view=aspnetcore-8.0#blazor-hub-options

... which I think remains a problem. I think this is the second report that it isn't configuring the Blazor hub.

I'll remain 👂 here for how to address it. I may as well add the remaining questions on hub config here so that we can address this in other articles as well ...

kalai-logicsoft commented 11 months ago

Thanks for the update @guardrex, We look forward to more guidance on this.

ElliottBrand commented 11 months ago

While not exactly the same use-case, #52156 is also related to MapBlazorHub and throws the Ambiguous Route Error when an app needs to have more than one, so I figured I'd mention it here as well. This worked fine in .Net 7.

kcsahoo123 commented 9 months ago

Has there been any update on this? I am still getting the error An unhandled exception was thrown by the application. Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: The request matched multiple endpoints. Matches:

Blazor initializers when I am putting this code in program.cs in .net8 blazor interactive server app: app.MapRazorComponents() .AddInteractiveServerRenderMode(); app.MapBlazorHub(options => { options.CloseOnAuthenticationExpiration = true; }); app.MapRazorPages();

kalai-logicsoft commented 9 months ago

HI @kcsahoo123,

Still, we are facing this issue.

FM1973 commented 8 months ago

Same here. We are not able to set CloseOnAuthenticationExpiration in a .net 8 blazor web app.

ecs87 commented 8 months ago

Same here as well.

MapBlazorHub() which resides in the dll C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App\8.0.1\Microsoft.AspNetCore.Components.Server.dll are mapping endpoints that the following method (in Program.cs) has already mapped: app.MapRazorComponents().AddInteractiveServerRenderMode();

IE: In :\Program Files\dotnet\shared\Microsoft.AspNetCore.App\8.0.1\Microsoft.AspNetCore.Components.Server.dll on lines 81 - 89:

image

Therefore, we can't have app.MapRazorComponents().AddInteractiveServerRenderMode() and app.MapBlazorHub(option => { option.CloseOnAuthenticationExpiration = true; }); in Program.cs at the same time or else it throws a AmbiguousMatchException.

halter73 commented 8 months ago

And we didn't know where to move the endpoint configuration to, which was previously being done in MapBlazorHub. Our previous call looked like this:

This issue is not being tracked by #54080. Unfortunately, configuring the hub used by AddInteractiveServerRenderMode with MapBlazorHub will not work. For .NET 8, you'll be forced to either:

ecs87 commented 8 months ago

Thank you, Stephen! It made me realize...I'm an idiot and our auth issues with InteractiveServer were more related to that rendering mode than the MapBlazorHub method because MapBlazorHub in Program.cs (combined with app.MapRazorComponents().AddInteractiveServerRenderMode()) and utilizing then setting the nodes in App.razor to @rendermode="InteractiveServer" made blazor.server.js error 500 in the browser console and threw everything into Static Server Side rendering mode (which works with auth when changing routes).

The only reason I was using MapBlazorHub in my Program.cs was to fix InteractiveServer mode not checking auth on route changes. Perhaps this warrants a different issue or more research.

kswami74 commented 6 months ago

Hi, you can also try mapping the Blazor hub to a different path: app.MapBlazorHub("/app")

jvelezc commented 3 months ago

No idea why this worked app.MapBlazorHub("APP"); But if you add random string in there the error goes away.

kalai-logicsoft commented 2 months ago

@jvelezc

No idea why this worked app.MapBlazorHub("APP"); But if you add random string in there the error goes away.

This will work because you are mapping the hub to a different endpoint, the change will throw the Blazor hub away / out of razor components, and the required config.CloseOnAuthenticationExpiration = true; will not work including any of the configuration which can be set from the MapBlazorHub.

Actually, it is not solving the problem, it is throwing the problem with the required options away..