Blazor @page route url define with variable
Asked Answered
P

4

29

I have a question for Blazor Server Side.

I want to @page route url define with variable or property.

I can use now with below default method

@page "/route-url"

<h1>Page Test</h1>

@code {
    
}

But i want use like as below method

@page MenuItem.Role

<h1>Page Test</h1>

@code {
    
}

I'm tried above method then throwed exception. Like as below exception.

C:\Projects\TestBlazorProject\Pages\TestPage.razor(1,7): error RZ1016: The 'page' directive expects a string surrounded by double quotes. [C:\Projects\TestBlazorProject\TestBlazorProject.csproj]

How to define @page route url with any different variable or any class property?

Pangenesis answered 31/3, 2021 at 20:13 Comment(0)
S
52

Can this be done?

Yes

How?

Page file

@attribute [Route(PageRoute.TaskList)]

<div>PAGE HTML HERE</div>

@code{ ... }

PageRoute.cs:

public static class PageRoute
{
    public const string TaskList = "/route-url";
}

Explanation

The page directive gets compiled down to an attribute and has the same restrictions as C# attributes.

You can use the @attribute with the [Route] attribute and use string concatenation instead of string interpolation to define a constant for the route, since that's what the C# compiler supports.

Why would anybody do this?

This is a good coding practice, because you are not hardcoding the page/component name in multiple places, but only in one place.
So one fine day when you manager asks to change page name "Earth" to "Planet3",
you just change it in 1 place, and be 98% sure that your app wont crash because of it.

Sweven answered 16/4, 2022 at 4:24 Comment(4)
The attribute must be a const like : public const string TaskList = "/tasklist";Shapely
It would be nice if you could refer to the constant in the attribute as well as in NavLinks or a tags, but the attributes need to have the / prefix, and the hrefs can't.Acidulant
Would it be possible to configure an url parameter in the string as well? e.g. public const string TaskList = "/route-url/view/{Id}" ?Haematite
Yes: I found the answer here. #76588064Haematite
S
9

@page isn't C#, it's Razor talk. Razor files are pre-compiled into c# files during compilation.

As an example, this is the important section of the C# pre-compiled file for Index.razor (Index.razor.g.cs):

[Microsoft.AspNetCore.Components.RouteAttribute("/")]
public partial class Index : Microsoft.AspNetCore.Components.ComponentBase
{
    #pragma warning disable 1998
    protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
    {
        __builder.AddMarkupContent(0, "<h1>Hello, world!</h1>\r\n\r\nWelcome to your new app.\r\n\r\n");
        __builder.OpenComponent<Blazor.Starter.Shared.SurveyPrompt>(1);
        __builder.AddAttribute(2, "Title", "How is Blazor working for you?");
        __builder.CloseComponent();
    }
    #pragma warning restore 1998
}

Note that @page has become a compile time attribute [Microsoft.AspNetCore.Components.RouteAttribute("/")]. It's fixed at compiletime, you can't change it at runtime.

Routes are set this way because the router builds a routemap - essentially a dictionary of route url/component class pairs - when the application loads by trawling the application assembly for any component classes with a Route attribute. On a routing event it reads the new url, finds the component class and loads it into the layout. Any variables - stuff in curly brackets - get passed into the component as Parameters.

You haven't made it clear what the line below is supposed to do:

@page MenuItem.Role

  1. Do you want to capture a variable supplied in the route into MenuItem.Role?
  2. Do you want to set this page's route to the value in MenuItem.Role?

If 1, either the other answers will work for you. If 2, you'll need to consider writing your own router. A subject beyond a simple answer here.

Sandor answered 1/4, 2021 at 8:50 Comment(7)
I want to set this page's route to the value in MenuItem.Role. I'm currenlty using from above recomendationsPangenesis
You're into building your own router - have a look at this article - chrissainty.com/building-a-custom-router-for-blazor. Showing you how to do that is beyond the scope of answers to question here and requires a lot more detailed specification information aka software consulting.Sandor
Custom router is not solution for me becasuse complex solution for me but thanks for share.Pangenesis
This solution works very well! If you have a CSHMLT file then you have to use the following attribute: [Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadata("RouteTemplate", "/YourPageUrl")]Dachia
My usecase is to have only one place for the path, in case it changes.Cardiac
@Dachia RazorCompiledItemMetadata works well thanks. Just don't forget to also add @page, withtout it, it doesn't work.Mccready
Why don't they allow the use of a const value though?Liquid
M
3

I think you can achieve that by following.

@page "/{Role}"

@code{
    [Parameter]
    public string Role { get; set; }
}
Monotype answered 31/3, 2021 at 20:19 Comment(3)
I'm currently using with this method but i want all route paths organize and store in MenuItem classPangenesis
@Pangenesis you can do it via @attribute, for example see my answerSweven
This is not working in Blazor Server App. I tried like "@page "/{MyConstantVariable}" "Spalla
S
3

Building off of the above you can I was able to get this to work with the code isolation approach.

Client/Pages/Foo/
----Index.razor
----Index.cs

namespace Client.Pages.Foo;
[Microsoft.AspNetCore.Components.RouteAttribute(Path)]
public partial class Index
{
    public const string Path = "/Foo";
}
Spend answered 3/2, 2022 at 18:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.