I have a quite complicated existing asp.net core site with an SPA. This SPA uses # for routing, so all of the existing razor pages and API endpoints just work.
I first tried to host just using app.UseBlazorFrameworkFiles()
, but all sorts of things break with this.
Then I tried to put it in a sub folder: app.UseBlazorFrameworkFiles("/UI")
, updated the main Index.cshtml
to redirect to /UI/
and serve the appropriate HTML there in /Areas/UI/Pages/Index.cshtml
and added <StaticWebAssetBasePath>UI</StaticWebAssetBasePath>
and hacked the AddHttpClient
to use baseaddress of the whole site.
This works... Except when it doesn't, in particularly when using a url to a subpage in blazor or a from blazor navigating to a route that doesn't exists. This will end up visiting the hosted site and serve my 404 instead.
I then tried various variations of
app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/UI/"), blazor => {
blazor.UseEndpoints(endpoints => {
endpoints.MapFallbackToAreaPage("/UI/{*path:nonfile}", "/", "UI");
});
});
Result: InvalidOperationException: Cannot find the fallback endpoint specified by route values: { page: /, area: UI }.
app.MapFallbackToAreaPage("/", "UI");
Result: InvalidOperationException: Cannot find the fallback endpoint specified by route values: { page: /, area: UI }.
app.MapFallbackToAreaPage("/Index", "UI");
Result: AmbiguousMatchException: The request matched multiple endpoints. Matches: /Index /Index
or any other sorts of variations I could come up with, all with the result of either a) blows up the existing configuration or b) blows up at startup or c) blows up when visting a page that doesn't exist.
Help please. How do I make this blazor hosted on my site?
TLDR; Fix it at the start of pipeline, not at the end (with mapfallback)
I was able to find a solution simply by hacking the pipeline and rewriting the request.
app.UseHttpsRedirection(); //after this
//host blazor in this folder
app.UseBlazorFrameworkFiles("/UI");
app.Use((ctx, next) => {
if (ctx.Request.Path.StartsWithSegments("/UI", out var rest) && !rest.StartsWithSegments("/"))
{
//detected paths that needs to be routed by Blazor and not server
ctx.Request.Path = new PathString("/UI/");
return next();
}
return next();
});
If this is placed after UseHttpsRedirection
and before everything else (can be after UseStaticFiles
also if the new path is a non-file, like a razor page), it will rewrite EVERYTHING like /UI/*
into /UI/
.