[SOLVED] Blazor server route prefix dynamic

Issue

I have an Blazor server Application and we need to set up an global route prefix that we can use to set specific data based on the prefix. Is there any solution for that?

Ex. We want this /company/{companyID}/
To be on Every route and have a Middleware or something similar to cath the companyID in.

endpoints.MapGet("/company/{companyID:regex(^[a-zA-Z]{{3,100}}(-[a-zA-Z+]{{3,100}})?$)}/{**rest}", async context =>
                {
                    var companyID = context.Request.RouteValues["companyID"]?.ToString()?.ToLower() ?? "default";
                    var restPath = context.Request.RouteValues["rest"]?.ToString()?.ToLower();

// Here i do stuff with the CompanyID
                    
                    // This is for now, but will redirect to /index without company/companyID. Here i just want to go on with the Ondex component and keep the url.
                    context.Response.Redirect(restPath == null ? "/" : $"/{restPath}");
                });
                
                endpoints.MapControllers();
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");

Solution

This may fit your requirements. It uses LocalStorage to persist the company name instead of cookies. I’ve set it up using the Blazor Server template.

Install Blazored.LocalStorage

First a Company Service

using Blazored.LocalStorage;

namespace Blazor.Company;

public class CompanyService
{
    private ILocalStorageService _localStorageService;

    public const string CompanyNameKey = "CompanyName";

    public string CompanyName { get; private set; } = string.Empty;

    public CompanyService(ILocalStorageService localStorageService)
        => _localStorageService = localStorageService;

    public async Task SetCompany(string company)
    {
        this.CompanyName = company;
        await _localStorageService.SetItemAsync<string>(CompanyNameKey, company);
    }

    public async Task<string> GetCompany()
    {
        this.CompanyName = await _localStorageService.GetItemAsync<string>(CompanyNameKey);
        return this.CompanyName;
    }
}

Program looks like this:

builder.Services.AddBlazoredLocalStorage();
builder.Services.AddScoped<CompanyService>();

Index looks like this:

page "/"
@page "/Company"
@page "/Company/{CompanyName}"

<PageTitle>Index</PageTitle>

@if (this.hasCompany && this.isSet)
{
    <div class="m-2 p-4 bg-success text-white">
        <h3>You work for : @CompanyService.CompanyName</h3>
    </div>
}
@if (this.isSet && !this.hasCompany)
{
    <div class="m-2 p-4 bg-danger text-white">
        You need to set up your company
    </div>
}

@code {
    [Parameter] public string CompanyName { get; set; } = string.Empty;

    private string companyName = string.Empty;

    private bool isSet = false;
    private bool hasCompany => !string.IsNullOrWhiteSpace(this.companyName);

    [Inject] private CompanyService? companyService { get; set; }
    private CompanyService CompanyService => companyService!;

    protected override void OnInitialized()
    {
        if (!string.IsNullOrWhiteSpace(this.CompanyName))
            companyName = this.CompanyName;
    }

    protected async override Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            if (string.IsNullOrWhiteSpace(this.companyName))
                companyName = await CompanyService.GetCompany();
            else
                await CompanyService.SetCompany(companyName);

            this.isSet = true;
            StateHasChanged();
        }
    }
}

Answered By – MrC aka Shaun Curtis

Answer Checked By – Clifford M. (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *