Home > database >  Redirect Specific Requests to a the Specific Component in Blazor wasm
Redirect Specific Requests to a the Specific Component in Blazor wasm

Time:07-27

I use Blazor wasm. I want to check all the requests to the Blazor App and if a request Url starts with @ like localhost:5000/@michel, redirect it to a specific component, like a middleware in asp core that can catch all requests. How can I do this?

CodePudding user response:

I'm making the assumption that under normal circumstances no route exists for @michel and you get a Sorry, there's nothing at this address. message.

In which case you should be able to modify the NotFound content of Router.

Here's the modified version of App. UserRouteFound is a new component that does the magic: it detects username requests and loads UserPage.

<Router AppAssembly="@typeof(App).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
    <NotFound>
        <UserRouteFound Layout="@typeof(MainLayout)" UserForm="@typeof(UserPage)">
            <PageTitle>Not found</PageTitle>
            <LayoutView Layout="@typeof(MainLayout)">
                <p role="alert">Sorry, there's nothing at this address.</p>
            </LayoutView>
        </UserRouteFound>
    </NotFound>
</Router>

UserNotFound.cs

It implements IComponent.

The key bits are:

  1. TryGetUserName checks if there is a @ and gets the username. This is simplistic, you probably want to be more specific and use a RegEx.

  2. We try and get a username in SetParametersAsync and populate _username.

  3. Render loads the component defined in UserForm instead of the Not Found content if we have a username.

The IComponent implementatiion stuff is fairly standard MS DotNetCore fare.

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;

namespace xxxxx;

public class UserRouteFound : IComponent
{
    private RenderHandle _renderHandle;
    private readonly RenderFragment _renderDelegate;
    private string? _username;

    [Inject] private NavigationManager NavigationManager { get; set; } = default!;

    [Parameter, EditorRequired] public Type Layout { get; set; } = default!;

    [Parameter, EditorRequired] public Type UserForm { get; set; } = default!;

    [Parameter] public RenderFragment? ChildContent { get; set; }

    public UserRouteFound()
        => _renderDelegate = Render;

    public void Attach(RenderHandle renderHandle)
        => _renderHandle = renderHandle;

    public Task SetParametersAsync(ParameterView parameters)
    {
        parameters.SetParameterProperties(this);

        if (UserForm == null)
            throw new InvalidOperationException($"The {nameof(RouteView)} component requires an IComponent UserForm class.");

        _username = null;
        if (TryGetUserName(out string? username))
            _username = username;

        _renderHandle.Render(_renderDelegate);
        return Task.CompletedTask;
    }

    protected bool TryGetUserName(out string? value)
    {
        string? username = null;
        var url = NavigationManager.Uri;

        if (url.Contains("@"))
            username = url.Substring(url.IndexOf("@"));

        value = username;
        return value is not null;
    }

    protected virtual void Render(RenderTreeBuilder builder)
        => _ = _username is not null 
            ? RenderUserFound(builder) 
            : RenderNotFound(builder);

    private bool RenderUserFound(RenderTreeBuilder builder)
    {
        builder.OpenComponent<LayoutView>(0);
        builder.AddAttribute(1, nameof(LayoutView.Layout), Layout);
        builder.AddAttribute(2, nameof(LayoutView.ChildContent), this.RenderUserForm);
        builder.CloseComponent();
        return true;
    }

    private bool RenderNotFound(RenderTreeBuilder builder)
    {
        builder.AddContent(0, this.ChildContent);
        return true;
    }

    private RenderFragment RenderUserForm => (RenderTreeBuilder builder) =>
    {
        builder.OpenComponent(0, this.UserForm);
        builder.AddAttribute(1, "UserName", _username);
        builder.CloseComponent();
    };
}

UserPage

Here's a very simplistic "UserForm".

<h3>UserPage</h3>

<div >
    @this.UserName
</div>

@code {
    [Parameter] public string UserName { get; set; } = string.Empty;
}
  • Related