學習ASP.NET Core Blazor編程系列十——路由(中)

 學習ASP.NET Core Blazor編程系列一——綜述

 

五、通過路由傳參

          通過上面的示例,我們使用<a>標籤實現了頁面之間的跳轉,但是通常我們開發的Web應用程序,通過http的url進行頁面跳轉時,會進行參數傳遞,以方便我們跳轉到的新頁面進行一些前置操作。下面我們示例來學習如何從「圖書列表」頁面,使用鼠標點擊「編輯「按鈕進行跳轉時,傳遞一個參數(例如圖書ID)給新的頁面「AddBook」。我們在「圖書列表」頁面中的將圖書ID這個參數,在進行頁面跳轉時同步傳遞給「AddBook」頁面,並且通過這個ID,查詢到相應的圖書信息,顯示在AddBook頁面上。

六、 通過path傳參

       通過url傳參一般有兩種方式,一種是直接把參數組合在URL的路徑(path)里。路由器使用路由參數以相同的名稱填充相應的組件參數。 路由參數名不區分大小寫。 在下面的示例中,對 /AddBook/3發出請求,參數Id將URL路徑中的參數值賦給AddBook組件的 Id屬性。

1. 在Visual Studio 2022的解決方案資源管理器中,找到 BookIndex.razor 組件,使用鼠標左鍵雙擊,在文本編輯器中打開,然後修改代碼如下:

@page "/BookIndex"
@using BlazorAppDemo.Models
@using Microsoft.EntityFrameworkCore
 

@inject IDbContextFactory<BookContext> dbFactory
 

<PageTitle>圖書列表</PageTitle>

<h3>圖書列表</h3>

<table class="table-responsive" width="90%"> 
    <tr><td>Name</td>
    <td>Author</td>
    <td>Price</td>
    <td>ReleaseDate</td>
    <td>StockQty</td>
    <td>Qty</td>
    <td>操作</td>
 

    </tr>
    @foreach (var item in books)
    {
        <tr> 
        <td>@item.Name</td>
        <td>@item.Author</td>
        <td>@item.Price</td>
        <td>@item.ReleaseDate</td>
        <td>@item.StockQty</td>
        <td>@item.Qty</td>
            <td><a href="/AddBook/@item.ID">編輯</a></td>
    </tr>
 
    }
</table>
 
@code {
    private   static BookContext _context;
    private List<Book> books = new List<Book>();
    protected override async Task OnInitializedAsync()
    {
        _context = dbFactory.CreateDbContext();
        books=_context.Book.ToList();
        await base.OnInitializedAsync();
    }
}
      上面代碼中,<a>標籤的代碼是通過把Id組合到URL的路徑(path)上,將圖書的ID傳遞給AddBook頁面。

      2. 在Visual Studio 2022的解決方案資源管理器中,找到 AddBook.razor 組件,使用鼠標左鍵雙擊,在文本編輯器中打開,AddBook.razor組件中添加一行@page開頭的路由模板。本示例中使用一個「/AddBook/{Id}」 路由模板來匹配Id,並且在代碼中聲明一個Id屬性,並添加特性[Parameter]。修改代碼如下:

@page "/AddBook"
@page "/AddBook/{Id}"

@using BlazorAppDemo.Models
@using Microsoft.EntityFrameworkCore
@inject IDbContextFactory<BookContext> dbFactory
 
<h3>AddBook</h3>
 
<EditForm Model=@addBook OnValidSubmit=@ValidSubmitInfo  OnInvalidSubmit=@InvalidSubmitInfo>
    <DataAnnotationsValidator />
    <ValidationSummary />
 
    <div>@Message</div>
    <p> 圖書名稱:
    <InputText @bind-Value=addBook.Name></InputText>
        <ValidationMessage For="@(() => addBook.Name)" />
    </p>
    <p>作者:
    <InputText @bind-Value=addBook.Author></InputText>
        <ValidationMessage For="@(() => addBook.Author)" />
    </p>
    
    <p>出版日期:
    <InputDate @bind-Value=addBook.ReleaseDate></InputDate>
     </p>
    <p>價格:
    <InputNumber @bind-Value=addBook.Price></InputNumber>
     </p>
    <p>類型:
     <InputText @bind-Value=addBook.Type></InputText>
        <ValidationMessage For="@(() => addBook.Type)" />
      </p>
    <p>總頁數:
    <InputNumber @bind-Value=addBook.TotalPages></InputNumber>
     </p>
    <p>庫存數量:
    <InputNumber @bind-Value=addBook.StockQty></InputNumber>
        <ValidationMessage For="@(() => addBook.StockQty)" />
     </p>
    <p>已租數量:
    <InputNumber @bind-Value=addBook.Qty></InputNumber>
    </p>
    <input type="submit" class="btn btn-primary" value="Save" />
 
</EditForm>
@code {
    private string Message = string.Empty;
    private static BookContext _context;
    private Models.Book addBook = new Book();
    protected override Task OnInitializedAsync()
    {
        _context = dbFactory.CreateDbContext();
        return base.OnInitializedAsync();
    }
    [Parameter]
    public string Id { get; set; }
 
    protected override void OnParametersSet()
    {
        Id = Id ?? "0";
        if (!string.IsNullOrEmpty(Id))
        {
            if (Id!="0")
            {
                int iId = int.Parse(Id);
                var book = _context.Book.Find(iId);
                if (book!=null)
                {
                    addBook = book;
                }
            }
           
        }
    }
 
 
    private void ValidSubmitInfo(EditContext editContext)
    {
 
        if (editContext.Model is  Book addBook)
        {
            Message = "你編輯的不是圖書信息,校驗通過。正在保存。";
           
        }
    }
    private void InvalidSubmitInfo(EditContext editContext)
    {
        if (editContext.Model is  Book addBook)
       
        {
            Message = "你編輯的圖書信息校驗不通過,請修改。";
        }
 
    }
 
    private void Save(EditContext editContext)
    {
        bool dataIsValid = editContext.Validate();
        if (!dataIsValid)
        {
            Message = "你編輯的圖書信息校驗不通過,請修改。";
            return;
        }

        if (editContext.Model is not Book addBook)
        {
            Message = "你編輯的不是圖書信息。";
            return;
        }

        _context.Add(editContext.Model);
        int cnt=  _context.SaveChanges();
        if (cnt>0)
        {
        Message = "圖書信息保存成功!";

        }else
       {
            Message = "圖書信息保存失敗!";
       }

    }

}

      3.在Visual Studio 2022的菜單欄上,找到「調試à開始調試」或是按F5鍵,Visual Studio 2022會生成BlazorAppDemo應用程序,並在瀏覽器中打開Home頁面,我們我們使用鼠標左鍵點擊左邊菜單上的「圖書列表」菜單項,瀏覽器會顯示我們修改過的圖書列表頁面,將鼠標指針懸停在「編輯」鏈接上可以查看,鏈接背後的URL值,我們會在瀏覽器的左下角看到//localhost:7110/AddBook/3這樣的地址。如下圖。

      4.在瀏覽器中,使用鼠標左鍵點擊我們要修改的圖書信息的「編輯」按鈕,瀏覽器會自動跳轉到AddBook頁面,並將我們需要修改的圖書信息顯示出來。如下圖。

 

七、路由約束

路由約束強制在路由段和組件之間進行類型匹配。

在以下示例中,到AddBook組件的路由僅在以下情況下匹配:

  • 請求 URL 中存在
    Id 路由段。
  • Id 段是一個整數 (int) 類型。
Pages/AddBook.razor:

@page "/AddBook/{Id:int}"

<h1>Book Id: @Id</h1>

@code {

    [Parameter]
    public int Id { get; set; }

}

備註

    路由約束不適用於查詢字符串值。

    下表中顯示的路由約束可用。 有關與固定區域性匹配的路由約束,請參閱表下方的警告了解詳細信息。

約束

示例

匹配項示例

固定條件區域性 匹配

bool

{active:bool}

true, FALSE

datetime

{dob:datetime}

2016-12-31, 2016-12-31 7:32pm

decimal

{price:decimal}

49.99, -1,000.01

double

{weight:double}

1.234, -1,001.01e8

float

{weight:float}

1.234, -1,001.01e8

guid

{id:guid}

CD2C1638-1638-72D5-1638-DEADBEEF1638,

{CD2C1638-1638-72D5-1638-DEADBEEF1638}

int

{id:int}

123456789, -123456789

long

{ticks:long}

123456789, -123456789

警告

驗證 URL 的路由約束並將轉換為始終使用固定區域性的 CLR 類型(例如 int 或 DateTime)。 這些約束假定 URL 不可本地化。