I have an app that I would like to make country-specific such that different pages are shown based on country, for the same route.
For every country, I have an RCL that is lazy-loaded, with custom components. My goal is that when I go to domain.com/
or domain.com/shop
, the country-specific component will load from a Razor Class Library. This means that multiple components have the same route across RCLs.
As an example:
domain.com/shop
from USApp.dll
.domain.com/shop
from CanadaApp.dll
.The country is stored in local storage in the browser and can be changed antime.
In what ways can I achieve this? There are no docs on custom routing for this case.
Turns out the solution is quite simple. As pointed out by @MisterMagoo you can just change the additional assemblies on the fly.
This is what I ended up with:
App.razor
:
@using System.Reflection
@using Blazored.LocalStorage
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.WebAssembly.Services
@using Microsoft.Extensions.Logging
@inject LazyAssemblyLoader AssemblyLoader
@inject ILogger<App> Logger
@inject ILocalStorageService localStorageService
<CascadingValue Value="AppCountry">
<CascadingAuthenticationState>
<Router AdditionalAssemblies="@lazyLoadedAssemblies" AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true" OnNavigateAsync="@OnNavigateAsync">
<Found Context="routeData">
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
<NotAuthorized>
@if (!context.User.Identity.IsAuthenticated)
{
}
else
{
<p>You are not authorized to access this resource.</p>
}
</NotAuthorized>
</AuthorizeRouteView>
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</CascadingAuthenticationState>
</CascadingValue>
App.razor.cs
:
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Routing;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
namespace Client
{
public partial class App : ComponentBase
{
private List<Assembly> lazyLoadedAssemblies = new();
public string AppCountry { get; set; }
private async Task OnNavigateAsync(NavigationContext args)
{
try
{
AppCountry = await localStorageService.GetItemAsync<string>("Country");
Console.WriteLine(AppCountry);
if (string.IsNullOrEmpty(AppCountry))
{
AppCountry = "RO";
}
IEnumerable<Assembly> assemblies = Enumerable.Empty<Assembly>();
switch (await localStorageService.GetItemAsync<string>("Country"))
{
case "RO":
assemblies = await AssemblyLoader.LoadAssembliesAsync(
new[]
{
"RomanianAppLayout.dll"
});
break;
case "US":
assemblies = await AssemblyLoader.LoadAssembliesAsync(
new[]
{
"USAppLayout.dll"
});
break;
default:
await localStorageService.SetItemAsync("Country", "RO");
goto case "RO";
}
lazyLoadedAssemblies.Clear();
lazyLoadedAssemblies.AddRange(assemblies);
}
catch (Exception ex)
{
Logger.LogError("Error: {Message}", ex.Message);
}
}
}
}