Razor Page入門 - 2

by vivid 27. 五月 2020 11:05

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

這篇文章將延續《Razor Page入門 - 1》一文的情境,介紹如何在Razor Page網站應用程式之中,利用服務(Services)與模型(Model)來存取資料顯示在網頁之中。

.NET Standard類別庫(.NET Standard Class Library)專案能夠在.NET Framework、.NET Core或Xamarin類型的專案之中重複使用,不同版本的.NET Standard可支援的框架可參考微軟官方文件:「https://docs.microsoft.com/zh-tw/dotnet/standard/net-standard」。我們想要在網站中,提供查詢圖書(Books)資料的功能,接下來我們要介紹如何建立.NET Standard類別庫專案,將資料存取邏輯封裝在專案之中,以便於重複使用。

建立.NET Standard類別庫專案

在目前的方案之中加入新專案。從「Solution Explorer」視窗 -「Solutions ‘MyRazorWeb’ 」項目上方,按滑鼠右鍵,從快捷選單選擇「Add」- 「New Project」項目,請參考下圖所示:

clip_image002

圖 1:加入新.NET Standard類別庫專案。

從「Add a new project」對話盒中,確認視窗上方程式語言選取「C#」,平台選取「All platforms」;專案類型選取「All project types」,然後選取下方清單中的「Class Library(.NET Standard)」項目,再按下「Next」按鈕,請參考下圖所示。

clip_image004

圖 2:建立「Class Library(.NET Standard)」範本專案。

在「Configure your new project」對話盒中,設定專案名稱,我們命為「MyModels」,以及設定專案存放路徑,再按下「Create」按鈕,請參考下圖所示:

clip_image006

圖 3:設定專案名稱與專案存放路徑。

刪除「MyModels」資料夾中的「Class1.cs」類別檔,從「Solution Explorer」視窗 -「Class1.cs」檔案上方,按滑鼠右鍵,從快捷選單選擇「Delete」項目,請參考下圖所示:

clip_image008

圖 4:刪除「Class1.cs」類別檔。

接著我們要在「MyModels」專案中加入類別來描述圖書相關資訊,在「Solution Explorer」視窗「MyModels」專案項目上方,按滑鼠右鍵,從快捷選單選擇「Add」- 「Class」項目,請參考下圖所示:

clip_image010

圖 5:加入新類別。

在「MyModels」專案中加入Category」類別。從「Solution Explorer」視窗 -「MyModels」項目上方,按滑鼠右鍵,從快捷選單選擇「Add」-「New Item」項目,在「Add New Item」對話盒中選取「Class」項目,並設定名稱為「Category」,請參考下圖所示:

clip_image012

圖 6:加入模型類別。

在「Category.cs」檔案之中加入程式碼,定義一個列舉型別,表列圖書分類,請參考以下程式碼:

Category.cs

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

namespace MyModels {
  public enum Category {
    Arts, Business, Commics, Cooking, Computers, History, Literature, Sports, Travel
  }

}


重複上個步驟,在「MyModels」專案中加入「Book.cs」檔案,然後在其中定義「Book」類別,包含以下屬性,請參考以下程式碼:

Book.cs

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

namespace MyModels {
  public class Book {
    public int Id { get; set; }
    public string Title { get; set; }
    public int Price { get; set; }
    public DateTime PublishDate { get; set; }
    public bool InStock { get; set; }
    public string Description { get; set; }
    public Category? Category { get; set; }
  }
}

建立服務專案

下一步是建立服務(Services)專案,其中包含程式碼以從資料來源取得資料。同樣為了將來能夠重複使用程式碼,我們將服務建立在一個新的.NET Standard類別庫專案中。從「Solution Explorer」視窗 -「Solutions ‘...’ 」項目上方,按滑鼠右鍵,從快捷選單選擇「Add」- 「New Project」項目,請參考下圖所示:

clip_image014

圖 7:加入新.NET Standard類別庫專案。

從「Add a new project」對話盒中,確認視窗上方程式語言選取「C#」,平台選取「All platforms」;專案類型選取「All project types」,然後選取下方清單中的「Class Library(.NET Standard)」項目,再按下「Next」按鈕,請參考下圖所示。

clip_image016

圖 8:建立「Class Library(.NET Standard)」範本專案。

在「Configure your new project」對話盒中設定專案名稱與專案存放路徑,再按下「Create」鍵,請參考下圖所示:

clip_image018

圖 9:設定專案名稱與專案存放路徑。

因為服務專案會使用到「Book」模型,我們先要設定「MyServices」服務專案相依於「MyModels」模型專案,從「Solution Explorer」視窗 -「MyServices」項目上方,按滑鼠右鍵,從快捷選單選擇「Add」- 「Reference」項目,請參考下圖所示:

clip_image020

圖 10:加入專案參考。

在「Reference Manager」視窗,選取「Projects」中的「MyModels」專案,然後按下「OK」按鈕,請參考下圖所示:

clip_image022

圖 11:選取要參考的專案。

刪除「MyServices」專案中「Class1.cs」類別檔,從「Solution Explorer」視窗 -「Class1.cs」檔案上方,按滑鼠右鍵,從快捷選單選擇「Delete」項目,請參考下圖所示:

clip_image024

圖 12:刪除「Class1.cs」類別檔。

在「MyServices」專案中加入類別,從「Solution Explorer」視窗 -「MyServices」項目上方,按滑鼠右鍵,從快捷選單選擇「Add」-「New Item」項目,在「Add New Item」對話盒中選取「Interface」項目,將檔案名稱命為「IBookRepository」,然後按下「Add」按鈕,請參考下圖所示:

clip_image026

圖 13:加入新介面檔案。

在「IBookRepository」檔案中定義一個「IBookRepository」介面,其中包含一個「GetAllBooks」方法的定義,請參考以下程式列表:

IBookRepository.cs

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

namespace MyServices {
  public interface IBookRepository {
    IEnumerable<Book> GetAllBooks();
  }
}

 

在「MyServices」專案中加入類別,從「Solution Explorer」視窗 -「MyServices」項目上方,按滑鼠右鍵,從快捷選單選擇「Add」-「New Item」項目,在「Add New Item」對話盒中選取「Class」項目,並設定名稱為「BookRepository」,請參考下圖所示:

clip_image028

圖 14:加入「BookRepository」類別。

在「BookRepository」類別加入以下程式碼,定義圖書資料,並實作「GetAllBooks」方法,回傳圖書資料:

BookRepository.cs

using MyModels;
using System;
using System.Collections.Generic;
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 IEnumerable<Book> GetAllBooks() {
      return _books;
    }
  }
}

 

設計Razor網頁

現在我們的專案中包含三個專案:

l 「MyModels」:定義網站應用程式中要使用到的「Book」與「BookCategory」模型。

l 「MyRazorWeb」:Razor Page網站應用程式。

l 「MyServices」:為.NET Standard 程式庫,包含資料存取服務程式。

Razor Page網站應用程式需要取回圖書資料顯示在網頁之中,因此「MyRazorWeb」專案需要參考「MyModels」與「MyServices」兩個專案。從「Solution Explorer」視窗 -「MyRazorWeb」項目上方,按滑鼠右鍵,從快捷選單選擇「Add」- 「Reference」項目,請參考下圖所示:

clip_image030

圖 15:加入專案參考。

在「Reference Manager」視窗,選取「Projects」中的「MyModels」與「MyServices」兩個專案,然後按下「OK」按鈕,請參考下圖所示:

clip_image032

圖 16:加入專案參考。

使用建構函式插入注入服務

在「MyRazorWeb」網站應用程式中要使用到「MyServices」定義的服務,需要在「Startup」類別的「ConfigureServices」方法之中進行註冊。我們希望使用到「IBookRepository」介面時,能夠提供一個「BookRepository」實體供網站應用程式使用,因此在程式中叫用了「AddSingleton」方法進行註冊,目前「Startup」類別的程式碼看起來如下所列:

Startup.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MyServices;

namespace MyRazorWeb {
  public class Startup {
    public Startup( IConfiguration configuration ) {
      Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices( IServiceCollection services ) {
      services.AddSingleton<IBookRepository , BookRepository>();
      services.AddRazorPages();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure( IApplicationBuilder app , IWebHostEnvironment env ) {
      if ( env.IsDevelopment() ) {
        app.UseDeveloperExceptionPage();
      }
      else {
        app.UseExceptionHandler( "/Error" );
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
      }

      app.UseHttpsRedirection();
      app.UseStaticFiles();

      app.UseRouting();

      app.UseAuthorization();

      app.UseEndpoints( endpoints => {
        endpoints.MapRazorPages();
      } );
    }
  }
}

 

修改「\Pages\Books\」資料夾中的「List.cshtml.cs」檔案,同樣使用建構函式插入注入「IBookRepository」服務,並在「OnGet」方法中,利用「GetAllBooks」方法取回圖書資料放到「Books」屬性之中,請參考以下程式碼:

List.cshtml.cs

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MyServices;

namespace MyRazorWeb {
  public class Startup {
    public Startup( IConfiguration configuration ) {
      Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices( IServiceCollection services ) {
      services.AddSingleton<IBookRepository , BookRepository>();
      services.AddRazorPages();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure( IApplicationBuilder app , IWebHostEnvironment env ) {
      if ( env.IsDevelopment() ) {
        app.UseDeveloperExceptionPage();
      }
      else {
        app.UseExceptionHandler( "/Error" );
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
      }

      app.UseHttpsRedirection();
      app.UseStaticFiles();

      app.UseRouting();

      app.UseAuthorization();

      app.UseEndpoints( endpoints => {
        endpoints.MapRazorPages();
      } );
    }
  }
}

最後修改「List.cshtml」加入Razor程式碼,「Html.DisplayNameFor」方法會取回「Book」類別套用的「Display」Attribute,若沒設定「Display」Attribute,則取回屬性的名稱,而「Html.DisplayFor」方法會取回「Book」類別屬性的值來顯示:

List.cshtml

@page
@model MyRazorWeb.ListModel
@{
    ViewData["Title"] = "List";
}

<h1> List </h1>


<table class="table" >
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor( model => ( (IList<MyModels.Book>) model.Books )[0].Id )
            </th>
            <th>
                @Html.DisplayNameFor( model => ( (IList<MyModels.Book>) model.Books )[0].Title )
            </th>
            <th>
                @Html.DisplayNameFor( model => ( (IList<MyModels.Book>) model.Books )[0].Price )
            </th>
            <th>
                @Html.DisplayNameFor( model => ( (IList<MyModels.Book>) model.Books )[0].PublishDate )
            </th>
            <th>
                @Html.DisplayNameFor( model => ( (IList<MyModels.Book>) model.Books )[0].InStock )
            </th>
            <th>
                @Html.DisplayNameFor( model => ( (IList<MyModels.Book>) model.Books )[0].Description )
            </th>
            <th>
                @Html.DisplayNameFor( model => ( (IList<MyModels.Book>) model.Books )[0].Category )
            </th>
        </tr>
    </thead>
    <tbody>
        @foreach ( var item in Model.Books ) {
            <tr>
                <td>
                    @Html.DisplayFor( modelItem => item.Id )
                </td>
                <td>
                    @Html.DisplayFor( modelItem => item.Title )
                </td>
                <td>
                    @Html.DisplayFor( modelItem => item.Price )
                </td>
                <td>
                    @Html.DisplayFor( modelItem => item.PublishDate )
                </td>
                <td>
                    @Html.DisplayFor( modelItem => item.InStock )
                </td>
                <td>
                    @Html.DisplayFor( modelItem => item.Description )
                </td>
                <td>
                    @Html.DisplayFor( modelItem => item.Category )
                </td>
            </tr>
        }
    </tbody>
</table>

選取Visual Studio開發工具「Build」-「Build Solution」項目編譯目前的專案,確認程式碼能正確編譯。在Visual Studio開發工具,按CTRL+F5執行網站首頁,執行結果參考如下:

clip_image034

圖 17:查詢資料。

Tags:

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

新增評論




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






NET Magazine國際中文電子雜誌

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

月分類Month List