I want to make an app where I need static pages on the base domain and my Blazor app on a subdirectory.
Example:
https://example.com
is where my static pages should be (like '/features' or '/pricing' or '/faq')
https://example.com/app
should be where my blazor website lives.
I've seen that I can pass in a PathString
to app.UseBlazorFrameworkFiles
but that does not work (app.UseBlazorFrameworkFiles(new PathString("/app")
).
My Blazor app is hosted on a .NET 5 WebApi project with gRPC.
Can someone point me to the right direction how to achieve this?
Thanks in advance!
The subdirectory name needs to appear in four places.
In the Startup.cs of your WebAPI project you need:
app.UseBlazorFrameworkFiles(new PathString("/app"));
and in endpoint config:
endpoints.MapFallbackToFile("/app/{*path:nonfile}", "app/index.html");
In the wwwroot/index.html file of the Wasm app:
<base href="/app/" />
In the CSProj file of the Wasm app:
<StaticWebAssetBasePath>app</StaticWebAssetBasePath>
Docs: https://docs.microsoft.com/en-us/aspnet/core/blazor/host-and-deploy/webassembly?view=aspnetcore-5.0#hosted-deployment-with-multiple-blazor-webassembly-apps
There's an example implementation here: https://github.com/javiercn/BlazorMultipleApps
If you have used the default Wasm template with Identity you'll find your client doesn't load properly because the static assets bundled inside microsoft.aspnetcore.components.webassembly.authentication aren't served up. To work around this change the src in index.html to an absolute path:
<script src="/_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"></script>
Other changes required for Identity to function:
"Clients": {
"BlazorApp.Client": {
"Profile": "SPA",
"RedirectUri": "https://localhost:44357/app/authentication/login-callback",
"LogoutUri": "https://localhost:44357/app/authentication/logout-callback"
}
}
I've looked at the answer from Daz, which does fix the problem when debugging/running a standalone product. My production environment is Kubernetes based however, and my ingress controller wouldn't route the request to the correct location e.g:
In my example, I have changed the usual 4 settings:
Everything was working barring the single file "Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js" which is an embedded file.
Since the file needs to come from the server, adjusting the file path in the client won't work, because it wouldn't be correctly routed by my ingress configuration. For my application, I dropped in a very simple middleware as follows:
// "/{app}/_content/{embedded-library-files}/{file}" requests need to be presented at root
app.Use(async (context, next) =>
{
HttpRequest request = context.Request;
var path = request.Path;
if (path.StartsWithSegments(new PathString("/app/_content")))
{
if (new string[] {
"/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"
}.Any(s => path.Value.EndsWith(s)))
{
request.Path = path.Value.Substring("/app".Length);
}
}
await next.Invoke();
});
You'd need an if clause for each folder, and an entry in the list for each file. Obviously this can be simplified if you know that the whole folder should be redirected.
Since rewriting the path in the server is invisible to the client application, this simple update fixes the problem.
Mark
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With