Razor Page入門 - 6

by vivid 19. 八月 2020 01:51

.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號:N200822102
出刊日期: 2020/8/19

這篇文章將延續《Razor Page入門 - 5》一文的情境,介紹當在ASP.NET Core Razor Page網站應用程式中新增資料的作業。

設計資料新增功能

先修改「MyServices」服務專案「IBookRepository」介面程式碼,新增一個「Create」方法,根據「editBook」參數「newBook」的值,來修新增書資料,並回傳修改過的「Book」物件。我們希望「Book.Id」自動編流水號,新的編號將會放在回傳的「Book」物件「Id」屬性中:

MyServices\IBookRepository.cs

using MyModels;
using System;
using System.Collections.Generic;
using System.Text;

namespace MyServices {
  public interface IBookRepository {
    IEnumerable<Book> GetAllBooks();
    Book GetBook( int id );
    Book Update( Book editBook );
    Book Create( Book newBook );
  }
}

 

接著我們在「BookRepository」類別中,實作「Create」方法,在方法中計算出流水號,請參考以下程式碼:

MyServices\BookRepository.cs

using MyModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyServices {
  public class BookRepository : IBookRepository {
    private List<Book> _books = null;
    public BookRepository() {
      _books = new List<Book>() {
         new Book() {
           Id = 1 ,
           Title = " Essential Programming Language " ,
           Price = 250 ,
           PublishDate = new DateTime( 2019 ,1,2 ) ,
           InStock = true ,
           Description = "Essential Programming Language "  ,
          Category = Category.Computers
         },
         new Book() {
           Id = 2 ,
           Title = " Telling Arts " ,
           Price = 245 ,
           PublishDate = new DateTime( 2019 , 4 , 15 ) ,
           InStock = true ,
           Description = " Telling Arts "  ,
          Category = Category.Arts
         },
           new Book() {
           Id = 3 ,
           Title = " Marvel " ,
           Price = 150  ,
           PublishDate = new DateTime( 2019 , 2, 21 ) ,
           InStock = true ,
           Description = " Marvel "  ,
          Category = Category.Commics
         },
          new Book() {
           Id = 4 ,
           Title = " The Beauty of Cook" ,
           Price = 450 ,
           PublishDate = new DateTime( 2019 ,12,2 ) ,
           InStock = true ,
           Description = " The Beauty of Cook "  ,
           Category = Category.Cooking
         }
      };
    }

    public Book Create( Book newBook ) {
      newBook.Id = _books.Max( b => b.Id ) + 1;
      _books.Add( newBook );
      return newBook;
    }

    public IEnumerable<Book> GetAllBooks() {
      return _books;
    }

    public Book GetBook( int id ) {
        return _books.FirstOrDefault( b => b.Id == id );
    }

    public Book Update( Book editBook ) {
      Book book  = _books.FirstOrDefault( b => b.Id == editBook.Id );
      if ( book!=null ) {
        book.Title = editBook.Title;
        book.Price = editBook.Price;
        book.PublishDate = editBook.PublishDate;
        book.InStock = editBook.InStock;
        book.Description = editBook.Description;
        book.Category = editBook.Category;
      }
      return book;
    }
  }
}

 

修改「_Layout.cshtml」檔案,加入一個選單選項,利用「Create」超連結連接到「Create」Razor Page,參考以下程式碼:

MyRazorWeb\Pages\Shared\_Layout.cshtml

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset = "utf-8" />
    <meta name = "viewport" content = "width=device-width, initial-scale = 1.0" />
    <title> @ViewData["Title"] – MyRazorWeb </title>
    <link rel = "stylesheet" href = "~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel = "stylesheet" href = "~/css/site.css" />
</head>
<body>
    <header>
        <nav class = "navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class = "container">
                <a class = "navbar-brand" asp-area = "" asp-page = "/Index"> MyRazorWeb </a>
                <button class = "navbar-toggler" type = "button" data-toggle = "collapse" data-target = ".navbar-collapse" aria-controls = "navbarSupportedContent"
                        aria-expanded = "false" aria-label = "Toggle navigation">
                    <span class = "navbar-toggler-icon"> </span>
                </button>
                <div class = "navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <ul class = "navbar-nav flex-grow-1">
                        <li class = "nav-item">
                            <a class = "nav-link text-dark" asp-area = "" asp-page = "/Index"> Home </a>
                        </li>
                        <li class = "nav-item">
                            <a class = "nav-link text-dark" asp-area = "" asp-page = "/Books/List"> Books </a>
                        </li>   <li class = "nav-item">
                            <a class = "nav-link text-dark" asp-area = "" asp-page = "/Books/Create"> Create </a>
                        </li>
                        <li class = "nav-item">
                            <a class = "nav-link text-dark" asp-area = "" asp-page = "/Privacy"> Privacy </a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class = "container">
        <main role = "main" class = "pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class = "border-top footer text-muted">
        <div class = "container">
            &copy; 2020 - MyRazorWeb - <a asp-area = "" asp-page = "/Privacy"> Privacy </a>
        </div>
    </footer>

    <script src = "~/lib/jquery/dist/jquery.min.js"> </script>
    <script src = "~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"> </script>
    <script src = "~/js/site.js" asp-append-version = "true"> </script>

    @RenderSection( "Scripts", required: false )
</body>
</html>

 

在「MyRazorWeb」Razor Page網站專案加入「Create」Razor Page。在「Solution Explorer」視窗,「MyRazorPage」專案 - 「Pages \ Books」資料夾項目上方,按滑鼠右鍵,從快捷選單選擇「Add」- 「Razor Page」項目,請參考下圖所示:

clip_image002

圖 1:加入「Razor Page」項目。

在「Add New Scaffolded Item」對話盒左方選取「Razor Pages」分類,然後選取「Razor Page」項目,按下「Add 」按鈕,請參考下圖所示:

clip_image004

圖 2:選取「Razor Page」項目。

在「Add Razor Page」對話盒中,設定Razor Page名稱為「Create」,勾選下方「Generate PageModel class」以及「Use a layout page」項目;然後按下「Add 」按鈕,請參考下圖所示:

clip_image006

圖 3:「Add Razor Page」對話盒。

在Visual Studio工具產生的「Create」Razor Page類別程式檔案加入以下程式碼,在「OnPost」方法中新增資料到集合中:

MyRazorWeb\Pages\Books\Create.cshtml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using MyModels;
using MyServices;

namespace MyRazorWeb.Pages.Books {
  public class CreateModel : PageModel {
    private readonly IBookRepository bookRepository;
    public CreateModel( IBookRepository bookRepository ) {
      this.bookRepository = bookRepository;
    }
    [BindProperty]
    public Book Book { get; set; }
    public IActionResult OnGet() {
      return Page();
    }
    public IActionResult OnPost() {
      if ( !ModelState.IsValid ) {
        return Page();
      }
      Book = bookRepository.Create( Book );
      return RedirectToPage( "List" );
    }
  }
}

 

修改「Create.cshtml」檔案中的程式碼,加入「Form」標簽,在標簽中利用標記協助程式(Tag Helper)來產生文字方塊、核取方塊與Select清單欄位:

MyRazorWeb\Pages\Books\Create.cshtml

@page
@model MyRazorWeb.Pages.Books.CreateModel
@{
    ViewData["Title"] = "Create";
}


<h1> Book Create </h1>
<hr />
<div class = "row">
    <div class = "col-md-8">
        <form method = "post">
            <div asp-validation-summary = "All" class = "text-danger"> </div>
            <div class = "form-group">
                <label asp-for = "Book.Title" class = "control-label"> </label>
                <input asp-for = "Book.Title" class = "form-control" />
                <span asp-validation-for = "Book.Title" class = "text-danger"> </span>
            </div>
            <div class = "form-group">
                <label asp-for = "Book.Price" class = "control-label"> </label>
                <input asp-for = "Book.Price" class = "form-control" />
                <span asp-validation-for = "Book.Price" class = "text-danger"> </span>
            </div>
            <div class = "form-group">
                <label asp-for = "Book.PublishDate" class = "control-label"> </label>
                <input asp-for = "Book.PublishDate" type = "date" class = "form-control" />
                <span asp-validation-for = "Book.PublishDate" class = "text-danger"> </span>
            </div>
            <div class = "form-group form-check">
                <label class = "form-check-label">
                    <input class = "form-check-input" asp-for = "Book.InStock" /> @Html.DisplayNameFor( model => model.Book.InStock )
                </label>
            </div>
            <div class = "form-group">
                <label asp-for = "Book.Description" class = "control-label"> </label>
                <input asp-for = "Book.Description" class = "form-control" />
                <span asp-validation-for = "Book.Description" class = "text-danger"> </span>
            </div>
            <div class = "form-group">
                <label asp-for = "Book.Category" class = "control-label"> </label>
                <select asp-for = "Book.Category" class = "form-control"
                        asp-items = "Html.GetEnumSelectList<MyModels.Category>()">
                    <option value = ""> Please Select </option>
                </select>
                <span asp-validation-for = "Book.Category" class = "text-danger"> </span>
            </div>
            <div class = "form-group">
                <input type = "submit" value = "Create" class = "btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-page = "List"> Back to List </a>
</div>

@section Scripts {
    @{ await Html.RenderPartialAsync( "_ValidationScriptsPartial" ); }
}

 

在新增「Create」Razor Page中,「PublishDate」Input欄位有稍做了一些修改,我們只需要填寫年、月、日,不需要時、分、秒,我們在標記協助程式中,設定「type="data"」來解決這個問題,參考以下程式碼:

<input asp-for = "Book.PublishDate" type = "date" class = "form-control" />

選取Visual Studio開發工具「Build」-「Build Solution」項目編譯目前的專案,確認程式碼能正確編譯。在Visual Studio開發工具,按CTRL+F5執行網站「Books/Create」Razor Page,執行結果參考如下,在表單欄位中輸入要新增的圖書資訊:

clip_image008

圖 4:新增資料。

若輸入的資料不符所需,以會透過驗證機制來顯示錯誤訊息,請參考下圖所示:

clip_image010

圖 5:資料驗證。

資料新增完成後將回到「List」頁面,顯示最新圖書清單資料,從中可以看到圖書的最新流水號碼,請參考下圖所示:

clip_image012

圖 6:顯示新增後的資料。

遠端驗證

現在新增資料的功能有一個新的需求,若圖書的名稱重複了,將視為錯誤,我們希望使用者輸入圖書名稱後就馬上進行檢查,不用等到圖書名稱、價格、出版日期、庫存、說明與圖書分類資料全都輸完提交之後,再進行檢查。

ASP.NET Core 3.x版新增一個「PageRemote」Attribute可以啟用遠端驗證(Remote Validation)的功能,所謂遠端驗證是指利用JavaScript程式碼將使用者輸入的資料,提交到伺服端程式做檢查,我們可以利用遠端驗證來達到新增資料的新需求。

Razor Pages遠端驗證功能要能生效,需要滿足以下需求:

  • 要透過jQuery Unobtrusive 驗證程式庫。Razor Pages範本專案中,已經安裝好這個套件了。
  • 在模型屬性上方套用「PageRemote」Attribute。
  • 在伺服端要撰寫Page Handler來處理驗證的動作。
  • 必需直接套用到PageModel類別的屬性;不可以是屬性值的子屬性(巢狀屬性)。

最後一個需求有一點麻煩,檢視「CreateModel」程式碼,我們想要驗證的恰巧是「CreateModel」類別「Book」屬性的「Title」屬性,也就是巢狀屬性。為此,我們需要變動模型的程式碼,修改Book」類別程式如下,將「Book」類別「Title」屬性的驗證Attribute程式碼註解,搬到「CreateModel」類別的「Title」屬性:

MyModel\Book.cs

using Microsoft.AspNetCore.Mvc.ModelBinding;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;

namespace MyModels {
  public class Book {
    [Display( Name = "圖書編號" )]
    public int Id { get; set; }
    [Display( Name = "圖書名稱" )]
    //[Required( ErrorMessage = "圖書名稱不可為空白" )]
    //[MaxLength( 50 , ErrorMessage = "長度不可超過 {0}" )]
    public string Title { get; set; }
    [Display( Name = "價格" )]
    [Range( 1 , int.MaxValue , ErrorMessage = "{0} 有效範圍在 {1} 與 {2} 之間" )]
    public int Price { get; set; }
    [Display( Name = "出版日期" )]
    public DateTime PublishDate { get; set; }
    [Display( Name = "庫存" )]
    public bool InStock { get; set; }
    [Display( Name = "說明" )]
    [MaxLength( 50 , ErrorMessage = "長度不可超過 {0}" )]
    public string Description { get; set; }
    [Display( Name = "圖書分類" )]
    public Category? Category { get; set; }
  }

}

 

在「CreateModel」類別中新增一個「Title」屬性,然後加上原來放在「Book」類別「Title」屬性上的套用「Required」、「MaxLength」驗證Attribute,同時套用「PageRemote」Attribute:

[Required( ErrorMessage = "圖書名稱不可為空白" )]
[MaxLength( 50 , ErrorMessage = "長度不可超過 {0}" )]
[BindProperty, PageRemote (
  ErrorMessage = "已存在重複的圖書名稱" ,
  AdditionalFields = "__RequestVerificationToken" ,
  HttpMethod = "post" ,
  PageHandler = "CheckTitle"
)]
public string Title { get; set; }

「PageRemote」Attribute包含以下常用屬性:

  • ErrorMessage:自訂錯誤訊息。
  • AdditionalFields:以逗號區隔的額外欄位名稱。以HTTP Post送出驗證請求時,必需包含當前age的Request Verification Token,否則會得到400號錯誤。
  • HttpMethod:要使用來送出請求的方式,預設是HTTP Get,可以設Get或Post。
  • PageHandler:用來進行驗證的Page Handler名稱。
  • PageName: Page名稱,若省略為目前使用的Page。

在「CreateModel」類別中新增一個「OnPostCheckTitle」方法,撰寫驗證邏輯,判斷圖書名稱是否已存在於集合中:

public JsonResult OnPostCheckTitle() {
  var valid = !( this.bookRepository.GetAllBooks().Count( b => b.Title == Title ) > 0 );
  return new JsonResult( valid );
}

 

這個方法必需回傳一個JSON格式的資料,來指明驗證的結果是成功(true)還是失敗(false)。還有一點要注意的是資料提交之後,在「OnPost」方法,需要將「Title」屬性的值更新到「Book.Title」屬性:

public IActionResult OnPost() {

      if ( !ModelState.IsValid ) {
        return Page();
      }
      Book.Title = Title;
      Book = bookRepository.Create( Book );
      return RedirectToPage( "List" );
    }

 

Create.cshtml.cs完整的程式碼如下:

MyRazorWeb\Pages\Books\Create.cshtml.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using MyModels;
using MyServices;

namespace MyRazorWeb.Pages.Books {
  public class CreateModel : PageModel {
    private readonly IBookRepository bookRepository;
    public CreateModel( IBookRepository bookRepository ) {
      this.bookRepository = bookRepository;
    }
    [BindProperty]
    public Book Book { get; set; }

    [Required( ErrorMessage = "圖書名稱不可為空白" )]
    [MaxLength( 50 , ErrorMessage = "長度不可超過 {0}" )]
    [BindProperty, PageRemote(
      ErrorMessage = "已存在重複的圖書名稱" ,
      AdditionalFields = "__RequestVerificationToken" ,
      HttpMethod = "post" ,
      PageHandler = "CheckTitle"
     )]
    public string Title { get; set; }

    public JsonResult OnPostCheckTitle() {
      var valid = !( this.bookRepository.GetAllBooks().Count( b => b.Title == Title ) > 0 );
      return new JsonResult( valid );
    }
    public IActionResult OnGet() {
      return Page();
    }
    public IActionResult OnPost() {

      if ( !ModelState.IsValid ) {
        return Page();
      }
      Book.Title = Title;
      Book = bookRepository.Create( Book );
      return RedirectToPage( "List" );
    }
   
  }
}

 

接著改寫「Create.cshtml」Razor Page顯示圖書名稱的 Input欄位之程式碼如下:

<label asp-for = "Book.Title" class = "control-label"> </label>
<input asp-for = "Title" class = "form-control" />
<span asp-validation-for = "Title" class = "text-danger"> </span>

 

Create.cshtml.cs完整的程式碼如下:

MyRazorWeb\Pages\Books\Create.cshtml

@page
@model MyRazorWeb.Pages.Books.CreateModel
@{
    ViewData["Title"] = "Create";
}


<h1> Book Create </h1>
<hr />

<div class = "row">
    <div class = "col-md-8">
        <form method = "post">
            <div asp-validation-summary = "All" class = "text-danger"> </div>
            <div class = "form-group">
                <label asp-for = "Book.Title" class = "control-label"> </label>
                <input asp-for = "Title" class = "form-control" />
                <span asp-validation-for = "Title" class = "text-danger"> </span>
                @*
                    <label asp-for = "Book.Title" class = "control-label"> </label>
                    <input asp-for = "Book.Title" class = "form-control" />
                    <span asp-validation-for = "Book.Title" class = "text-danger"> </span>
                *@
            </div>
            <div class = "form-group">
                <label asp-for = "Book.Price" class = "control-label"> </label>
                <input asp-for = "Book.Price" class = "form-control" />
                <span asp-validation-for = "Book.Price" class = "text-danger"> </span>
            </div>
            <div class = "form-group">
                <label asp-for = "Book.PublishDate" class = "control-label"> </label>
                <input asp-for = "Book.PublishDate" type = "date" class = "form-control" />
                <span asp-validation-for = "Book.PublishDate" class = "text-danger"> </span>
            </div>
            <div class = "form-group form-check">
                <label class = "form-check-label">
                    <input class = "form-check-input" asp-for = "Book.InStock" /> @Html.DisplayNameFor( model => model.Book.InStock )
                </label>
            </div>
            <div class = "form-group">
                <label asp-for = "Book.Description" class = "control-label"> </label>
                <input asp-for = "Book.Description" class = "form-control" />
                <span asp-validation-for = "Book.Description" class = "text-danger"> </span>
            </div>
            <div class = "form-group">
                <label asp-for = "Book.Category" class = "control-label"> </label>
                <select asp-for = "Book.Category" class = "form-control"
                        asp-items = "Html.GetEnumSelectList<MyModels.Category>()">
                    <option value = ""> Please Select </option>
                </select>
                <span asp-validation-for = "Book.Category" class = "text-danger"> </span>
            </div>
            <div class = "form-group">
                <input type = "submit" value = "Create" class = "btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-page = "List"> Back to List </a>
</div>

@section Scripts {
    @{ await Html.RenderPartialAsync( "_ValidationScriptsPartial" ) ; }
}

 

選取Visual Studio開發工具「Build」-「Build Solution」項目編譯目前的專案,確認程式碼能正確編譯。在Visual Studio開發工具,按CTRL+F5執行網站「Books/Create」Razor Page,執行結果參考如下,在表單欄位中輸入要新增的圖書資訊,若圖書的名稱重複了,只要按Tab鍵企圖讓游標移到下一個欄位時,就會進行檢查:

clip_image014

圖 7:遠端驗證。

除了「Title」欄位之外,「Book」類別的其它屬性也能正常的進行驗證,請參考下圖所示:

clip_image016

圖 8:資料驗證。

編輯資料

修改了MyModel\Book.cs類別的程式之後,我們圖書資料編輯的程式碼便無法驗證「Title」屬性的值是否正確,讓我們來修訂這個問題,首先修改「EditModel」程式碼,加入一個「Title」屬性,並套用「Required」、「MaxLength」驗證Attribute,同時套用「PageRemote」Attribute:

[Required( ErrorMessage = "圖書名稱不可為空白" )]
[MaxLength( 50 , ErrorMessage = "長度不可超過 {0}" )]
[BindProperty, PageRemote(
ErrorMessage = "已存在重複的圖書名稱" ,
AdditionalFields = "__RequestVerificationToken" ,
HttpMethod = "post" ,
PageHandler = "CheckTitle"
)]
public string Title { get; set; }

 

和資料新增不太一樣,資料編輯時,圖書名稱可以不修改,因此遠端驗證的Page Handler程式碼要修改如下:

public JsonResult OnPostCheckTitle() {
  var id = RouteData.Values["id"].ToString();
  var valid = !( this.bookRepository.GetAllBooks().Count( b => b.Title == Title  && b.Id.ToString() != id ) > 0 );
  return new JsonResult( valid );
}

Edit.cshtml.cs完整的程式碼如下:

MyRazorWeb\Pages\Books\Edit.cshtml.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using MyModels;
using MyServices;

namespace MyRazorWeb.Pages.Books {
  public class EditModel : PageModel {
    private readonly IBookRepository bookRepository;
    public EditModel( IBookRepository bookRepository ) {
      this.bookRepository = bookRepository;
    }
    [BindProperty]
    public Book Book { get; set; }

    [Required( ErrorMessage = "圖書名稱不可為空白" )]
    [MaxLength( 50 , ErrorMessage = "長度不可超過 {0}" )]
    [BindProperty, PageRemote(
    ErrorMessage = "已存在重複的圖書名稱" ,
    AdditionalFields = "__RequestVerificationToken" ,
    HttpMethod = "post" ,
    PageHandler = "CheckTitle"
   )]
    public string Title { get; set; }

    public JsonResult OnPostCheckTitle() {
      var id = RouteData.Values["id"].ToString();
      var valid = !( this.bookRepository.GetAllBooks().Count( b => b.Title == Title  && b.Id.ToString() != id ) > 0 );
      return new JsonResult( valid );
    }
    public IActionResult OnGet( int id ) {
      Book = bookRepository.GetBook( id );
      Title = Book.Title;

      if ( Book == null ) {
        return RedirectToPage( "/NotFound" );
      }

      return Page();
    }
    public IActionResult OnPost() {
      if ( !ModelState.IsValid ) {
        return Page();
      }
      Book.Title = Title;
      Book = bookRepository.Update( Book );
      return RedirectToPage( "List" );
    }
  }
}

 

接著改寫「Create.cshtml」Razor Page顯示圖書名稱的 Input欄位之程式碼如下:

<label asp-for = "Book.Title" class = "control-label"> </label>
<input asp-for = "Title" class = "form-control" />
<span asp-validation-for = "Title" class = "text-danger"> </span>

 

Edit.cshtml.cs完整的程式碼如下:

MyRazorWeb\Pages\Books\Edit.cshtml

@page "{id}"
@model MyRazorWeb.Pages.Books.EditModel
@{
    ViewData["Title"] = "Edit";
}

<h1> Book Edit</h1>
<hr />
<div class = "row">
    <div class = "col-md-8">
        <form method = "post">
            <div asp-validation-summary = "All" class = "text-danger"> </div>
            <input type = "hidden" asp-for = "Book.Id" />
            <div class = "form-group">
                <label asp-for = "Book.Title" class = "control-label"> </label>
                <input asp-for = "Title" class = "form-control" />
                <span asp-validation-for = "Title" class = "text-danger"> </span>
                @*
            <label asp-for = "Book.Title" class = "control-label"> </label>
                <input asp-for = "Book.Title" class = "form-control" />
                <span asp-validation-for = "Book.Title" class = "text-danger"> </span>
           *@
            </div>
            <div class = "form-group">
                <label asp-for = "Book.Price" class = "control-label"> </label>
                <input asp-for = "Book.Price" class = "form-control" />
                <span asp-validation-for = "Book.Price" class = "text-danger"> </span>
            </div>
            <div class = "form-group">
                <label asp-for = "Book.PublishDate" class = "control-label"> </label>
                <input asp-for = "Book.PublishDate" class = "form-control" />
                <span asp-validation-for = "Book.PublishDate" class = "text-danger"> </span>
            </div>
            <div class = "form-group form-check">
                <label class = "form-check-label">
                    <input class = "form-check-input" asp-for = "Book.InStock" /> @Html.DisplayNameFor( model => model.Book.InStock )
                </label>
            </div>
            <div class = "form-group">
                <label asp-for = "Book.Description" class = "control-label"> </label>
                <input asp-for = "Book.Description" class = "form-control" />
                <span asp-validation-for = "Book.Description" class = "text-danger"> </span>
            </div>
            <div class = "form-group">
                <label asp-for = "Book.Category" class = "control-label"> </label>
                <select asp-for = "Book.Category" class = "form-control"
                        asp-items = "Html.GetEnumSelectList<MyModels.Category>()">
                    <option value = ""> Please Select </option>
                </select>
                <span asp-validation-for = "Book.Category" class = "text-danger"> </span>
            </div>
            <div class = "form-group">
                <input type = "submit" value = "Save" class = "btn btn-primary" />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-page = "./List"> Back to List </a>
</div>


@section Scripts {
    <partial name = "_ValidationScriptsPartial" />
}

 

現在選取Visual Studio開發工具「Build」-「Build Solution」項目編譯目前的專案,確認程式碼能正確編譯。在Visual Studio開發工具,按CTRL+F5執行網站「Books/List」Razor Page,執行結果參考如下,點選某筆圖書後方的「Edit」超連結時,「Book」物件的「id」屬性值就以查詢字串的型式,傳遞到「Edit」Razor Page,若試圖將2號資料的圖書名稱改為和3號資料一樣的「Marvel」便自動顯示遠端驗證錯誤訊息:

clip_image018

圖 9:資料編輯遠端驗證功能。

然後確認其它欄位資料是否可以被驗證,或正確地儲存,請參考下圖所示:

clip_image020

圖 10:驗證資料。

Tags:

.NET Magazine國際中文電子雜誌 | ASP.NET Razor Pages | Visual Studio | 許薰尹Vivid Hsu

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List