Learning .NET MAUI Blazor (4), Routing

Web applications can connect multiple pages in series through URLs, and can jump to each other. Web applications mainly use a tag or server redirect to jump. Now the popular single-page application (SPA) realizes the jump through routing (Router), such as Vue, React, etc.

提示
Routing in MAUI is very different from routing in Blazor.

Routing for MAUI Blazor

In .NET MAUI Blazor applications, routing is Blazorthe routing rule to follow. It is also implemented through the routing component (Router). Open it and Main.razoryou can see:

<Router AppAssembly="@typeof(Main).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
    <NotFound>
        <LayoutView Layout="@typeof(MainLayout)">
            <p role="alert">Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>
<!--设置容器-->
<AntContainer />

There Router are two child nodes Foundwith NotFound.

  • The Found node contains a definition of RouteView. If a route definition is found, the corresponding page will be presented through RouteView, and a default template will be specified for all pages.
  • The NotFound node contains a LayoutView definition. If no routing definition is found, a specific page will be presented. The default template used here is that you MainLayoutcan also implement one yourself.

Define MAUI Blazor routes

In MAUI Blazor, routing definitions @pageare specified using directives. When creating Blazora component, it must be included @page '路径".

There is a big difference between MAUI routing and MAUI Blazor routing.
MAUI creates routes based on the Route attribute or through the explicit registration route through Routing.RegisterRoute.
MAUI Blazor is on the component, using the @page directive to specify.

When the Visual Studio 2022 compiler compiles a Razor component (.razor) with the @page directive, it will provide the component class with a RouteAttribute to specify the route of the component.

When the application starts, the application will scan the assembly specified by the AppAssembly attribute in the Router component, and collect the routing information of the Blazor components with RouteAttribute in the assembly.

When the application is running, the RouteView component:

  • Receive RouteData from Router along with all route parameters.
  • Renders the specified component using its layout, including any subsequent nested layouts.

Hint
Router does not interact with query string values.

When a route is matched

Based on the last code, we add a page. In Pagesthe directory, create a new Blazor component: pdf.razor. After creation, the default code is as follows:

<h3>pdf</h3>

@code {
    
    

}

We use @pagethe directive to specify the route as pdf. And write a few big characters.

@page "/PDF"

<Title Level="1">使用iTextSharp生成PDF文件</Title>

Then open it MainLayout.razorand add one to the menu MenuDataItem.

new MenuDataItem
{
    
    
	Path = "/PDF",
	Name = "PDF",
	Key = "PDF",
	Icon = "file-pdf"
}

Note:
Blazor components must start with an uppercase letter. If you start with a lowercase letter, an error will be reported when compiling:
Component 'xxx' starts with a lowercase character. Component names cannot start with a lowercase character
xxx is the name of the component.

Look at the effect of running:
insert image description here

When no route is matched

If no route is matched, NotFoundthe content defined by the node above will be rendered. First NotFoundmodify the content of the node a little bit!

<NotFound>
        <LayoutView Layout="@typeof(MainLayout)">
            <div style="text-align:center"><Icon Type="close-circle" Theme="twotone" TwotoneColor="#ff0000" Height="5em" Width="5em" /></div>
            <div style="margin-top:15px;text-align:center"><Title Level="3">页面走失!请确认输入的URL是否正确!</Title></div>
        </LayoutView>
    </NotFound>

In MainLayout.razor, add one MenuDataItemthat points to a page that doesn't exist:

new MenuDataItem
{
    
    
	Path = "/DataList",
	Name = "DataList",
	Key = "DataList",
	Icon = "appstore"
}

Look at the running effect:
insert image description here

Routing Jump

In many scenarios, in addition to clicking the menu on the left to jump, you also need to jump on the page. In addition to HTML tags, the jump supported by Blazor <a></a>also has a NavigationManagerclass.
NavigationManagerClasses are Microsoft.AspNetCore.Componentsunder a namespace.
under transformation Index.razor.

@page "/"
@inject NavigationManager navigationManager
<Title Level="1">Hello,DotNet宝藏库</Title>
<div style="margin-top:15px;"><Text Type="success">欢迎关注我的公众号!</Text></div>
<Divider />
<div style="margin-top:20px;"><a href="/Counter">使用a 标记跳转</a></div>
<div style="margin-top:20px;">
    <Button Danger Type="@ButtonType.Primary" OnClick="()=>DirectToCounter()">使用NavigationManager跳转</Button>
</div>
@code
{
    
    
    private void DirectToCounter()
    {
    
    
        navigationManager.NavigateTo("/Counter");
    }
}

At this time, whether you click a link or a button, you can jump to the response page!
insert image description here

routing parameters

During the routing process, parameter passing is often required, so that we can perform some operations after jumping to the new page.
There are two types of Blazor parameter passing: pathparameter passing and QueryStringparameter passing. We introduce these two methods of passing parameters separately.

path parameter

Path parameter passing is to combine the parameters in the URL path, and the page that receives the parameters needs to @pagefill in the parameters with the same name. And add Parameterfeatures to modify the parameters.
Transform firstCounter.razor

@page "/counter"
@page "/counter/{initNum}"

<Title Level="2">Counter</Title>
<Divider />
<p role="status">Current count: @currentCount</p>

<Button @onclick="IncrementCount" Type="primary">AntDesign 按钮</Button>
@code {
    
    
    [Parameter]
    public string initNum{
    
     get; set; }

    private int currentCount = 0;
    
    protected override void OnParametersSet()
    {
    
    
        if (!int.TryParse(initNum, out int num))
        {
    
    
            currentCount = 0;
        }else
        {
    
    
            currentCount = num;
        }
    }
    private void IncrementCount()
    {
    
    
        currentCount++;
    }
    
}


In the code, one is added @page "/counter/{initNum}". {initNum}It is the parameter.

Note that parameters are not case-sensitive , but for more standardization, it is recommended that all URLs be in lowercase, and c# codes should be named in camel case.
Also, Blazoroptional parameters are not supported, so if the initNum in this example is optional, you need to use @pageinstructions to define two routes, one containing initNumand the other not containing.
OnParametersSetor OnParametersSetAsyncin, we initNumassign to currentCount.
Modify the method Index.razorin the following DirectToCounter:

 private void DirectToCounter()
    {
    
    
        navigationManager.NavigateTo("/Counter/10");
    }

When it runs, when 使用NavigationManager跳转the button is clicked, Counter.razorthe currentCount in it is 10.
insert image description here

QueryString 传参

In addition to splicing parameters directly into the URL path (path), another common method of passing parameters is to pass parameters as QueryString to the jump page, such as "/Counter?initNum=3". We can get the query string of the request from the NavigationManager.Uri property.
change Index.razorin
<a href="/Counter">使用a 标记跳转</a>to<a href="/Counter?initNum=5">使用a 标记跳转</a>

Modify Counter.razor, import first NavigationManager.

@page "/counter"
@inject NavigationManager navigationManager

OnParametersSetGet parameters inside

	protected override void OnParametersSet()
    {
    
    
        //if (!int.TryParse(initNum, out int num))
        //{
    
    
        //    currentCount = 0;
        //}else
        //{
    
    
        //    currentCount = num;
        //}
        var query = new Uri(navigationManager.Uri).Query;
        Console.WriteLine(query);
    }

After the breakpoint, you can see that after Index.razorclicking the link to jump to Counter.razor, the parameters are obtained:
insert image description here
there is a problem here, the obtained parameters are not key-value pairs, but a string of strings. Different from our expectations. But fortunately, we can QueryHelpers.ParseQueryget the key-value pair information through .
1. Add dependencies:

PM> NuGet\Install-Package Microsoft.AspNetCore.WebUtilities -Version 2.2.0

2. Analyzing parameters

var queryDic = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(query);

insert image description here
The parameter value can be obtained. Complete the code:

protected override void OnParametersSet()
    {
    
    
        //if (!int.TryParse(initNum, out int num))
        //{
    
    
        //    currentCount = 0;
        //}else
        //{
    
    
        //    currentCount = num;
        //}
        var query = new Uri(navigationManager.Uri).Query;
        var queryDic = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(query);
        if (queryDic.ContainsKey("initNum"))
        {
    
    
            var count_str = queryDic["initNum"].ToString() ?? "";
            if (!int.TryParse(count_str, out int num))
            {
    
    
                currentCount = 0;
            }
            else
            {
    
    
                currentCount = num;
            }
        }
        else
        {
    
    
            currentCount = 0;
        }
        
    }

Run it to see the effect

insert image description here

routing constraints

Routing constraints enforce type matching between routing segments and components. As in the example just now initNum, we can write @page "/counter/{initNum:int}"that the routing constraint does not apply to the query string, which is the parameter passed by QueryString. Blazor supports the following constraint types:

  • bool
  • datetime
  • decimal
  • double
  • float
  • guid
  • int
  • long

Summarize

None yet, see you next time!

Click on the official account card below to follow me! Learn together and progress together!

Guess you like

Origin blog.csdn.net/sd2208464/article/details/128436933