Blazor入門100天 : 身份驗證和授權 (6)

2023-02-07 21:01:11

目錄

  1. 建立預設帶身份驗證 Blazor 程式
  2. 角色/元件/特性/過程邏輯
  3. DB 改 Sqlite
  4. 將自定義欄位新增到使用者表
  5. 腳手架拉取IDS檔案,在地化資源
  6. freesql 生成實體類,freesql 管理ids資料表
  7. 初始化 Roles,freesql 外來鍵 => 導航屬性
  8. 完善 freesql 和 bb 特性

本節原始碼

https://github.com/densen2014/Blazor100/tree/Blazor-教學15-6/b16blazorIDS2

截圖

安裝 FreeSql.Generator 命令列程式碼生成器生成實體類

對於此工具的使用可參考 https://github.com/dotnetcore/FreeSql/wiki/DbFirst , 也可直接執行命令檢視 FreeSql.Generator

安裝 dotnet-tool 生成實體類

dotnet tool install -g FreeSql.Generator

生成實體

  1. 專案右鍵新增 Model 目錄
  2. 右鍵選擇在終端中開啟
  3. 輸入命令
FreeSql.Generator  -NameOptions 0,0,0,0 -NameSpace b16blazorIDS2.Models.ids -DB "Sqlite,Data Source=../ids.db;" -Filter "View+StoreProcedure" -FileName "{name}.cs"

解釋

  • -NameOptions 0,0,0,0 首字母大寫, 首字母大寫,其他小寫, 全部小寫, 下劃線轉駝峰
  • -DB "Sqlite,Data Source=../ids.db;" 資料庫型別和連線字串,本例資料庫在上一級目錄,所以是../ids.db
  • -Filter "View+StoreProcedure" 不生成檢視和儲存過程

生成的實體

新增 BootstrapBlazor 元件庫

相關步驟往日文章有寫,不再贅述,只貼上關鍵部分.

參照Nuget包

        <PackageReference Include="BootstrapBlazor" Version="7.*" />
        <PackageReference Include="BootstrapBlazor.FontAwesome" Version="7.*" />
        <PackageReference Include="Densen.Extensions.BootstrapBlazor" Version="7.*" />
        <PackageReference Include="Densen.FreeSql.Extensions.BootstrapBlazor" Version="7.*" />
        <PackageReference Include="FreeSql.Provider.Sqlite" Version="3.2.685" />
        <PackageReference Include="Magicodes.IE.Core" Version="2.7.1" />
        <PackageReference Include="Magicodes.IE.Excel" Version="2.7.1" />
        <PackageReference Include="Magicodes.IE.Html" Version="2.7.1" />
        <PackageReference Include="Magicodes.IE.Pdf" Version="2.7.1" />
        <PackageReference Include="Magicodes.IE.Word" Version="2.7.1" />
        <PackageReference Include="HtmlToOpenXml.dll" Version="2.3.0" />
        <PackageReference Include="Haukcode.WkHtmlToPdfDotNet" Version="1.5.86" />

App.razor

<BootstrapBlazorRoot>
    <CascadingAuthenticationState>
    ...
    </CascadingAuthenticationState>
</BootstrapBlazorRoot>

_Imports.razor

新增的程式碼

@using BootstrapBlazor.Components
@using AME.Services
@using Blazor100.Service
@using System.Diagnostics.CodeAnalysis

Pages_Host.cshtml

    <!-- 刪掉這行 <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" /> !-->
    <link href="css/site.css" rel="stylesheet" />

    <!-- 新增下面兩行 !-->
    <link href="_content/BootstrapBlazor.FontAwesome/css/font-awesome.min.css" rel="stylesheet">
    <link href="_content/BootstrapBlazor/css/bootstrap.blazor.bundle.min.css" rel="stylesheet">
    <!-- 新增上面兩行 !-->

    ...

    <!-- <script src="_framework/blazor.server.js"></script> 之前增加這行 !-->
    <script src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js"></script>

新增匯入匯出服務

新建 Service 資料夾, 新建 ImportExportsService.cs 檔案

using BootstrapBlazor.Components;
using Magicodes.ExporterAndImporter.Core;
using Magicodes.ExporterAndImporter.Excel;
using Magicodes.ExporterAndImporter.Html;
using Magicodes.ExporterAndImporter.Pdf;
using Magicodes.ExporterAndImporter.Word;

namespace Blazor100.Service
{
    /// <summary>
    /// 通用匯入匯出服務類
    /// </summary>
    public class ImportExportsService
    {
        public enum ExportType
        {
            Excel,
            Pdf,
            Word,
            Html
        }

        public async Task<string> Export<T>(string filePath, List<T>? items = null, ExportType exportType = ExportType.Excel) where T : class, new()
        {
            switch (exportType)
            {
                case ExportType.Pdf:
                    var exporterPdf = new PdfExporter();
                    items = items ?? new List<T>();
                    var resultPdf = await exporterPdf.ExportListByTemplate(filePath + ".pdf", items);
                    return resultPdf.FileName;
                case ExportType.Word:
                    var exporterWord = new WordExporter();
                    items = items ?? new List<T>();
                    var resultWord = await exporterWord.ExportListByTemplate(filePath + ".docx", items);
                    return resultWord.FileName;
                case ExportType.Html:
                    var exporterHtml = new HtmlExporter();
                    items = items ?? new List<T>();
                    var resultHtml = await exporterHtml.ExportListByTemplate(filePath + ".html", items);
                    return resultHtml.FileName;
                default:
                    IExporter exporter = new ExcelExporter();
                    items = items ?? new List<T>();
                    var result = await exporter.Export(filePath + ".xlsx", items);
                    return result.FileName;
            }
        }

        public async Task<(IEnumerable<T>? items,string error)> ImportFormExcel<T>(string filePath) where T : class, new()
        {
            IExcelImporter Importer = new ExcelImporter();
            var import = await Importer.Import<T>(filePath);
            if (import.Data == null ) 
            {
                return (null, import.Exception.Message);
            }
            return (import.Data!.ToList(),""); 
        }
 
    }
}

Program.cs

頂上新增

using Densen.DataAcces.FreeSql;
using Blazor100.Service;

builder.Services.AddSingleton<WeatherForecastService>(); 下面新增

builder.Services.AddFreeSql(option =>
{
    option.UseConnectionString(FreeSql.DataType.Sqlite, "Data Source=ids.db;")  //也可以寫到組態檔中
#if DEBUG
         //開發環境:自動同步實體
         .UseAutoSyncStructure(true)
         .UseNoneCommandParameter(true)
    //偵錯sql語句輸出
         .UseMonitorCommand(cmd => System.Console.WriteLine(cmd.CommandText))
#endif
    ;
});
builder.Services.AddSingleton(typeof(FreeSqlDataService<>));

builder.Services.AddTransient<ImportExportsService>();
builder.Services.AddDensenExtensions();
builder.Services.ConfigureJsonLocalizationOptions(op =>
{
    // 忽略文化資訊丟失紀錄檔
    op.IgnoreLocalizerMissing = true;
});

管理頁面

Pages 新增元件 DataAdmin.razor

@page "/DataAdmin"
@using b16blazorIDS2.Models.ids 
@using static Blazor100.Service.ImportExportsService

<PageTitle>管理</PageTitle>

 <Tab IsLazyLoadTabItem="true">
     <TabItem Text="Users">
         <Table TItem="AspNetUsers"
                IsPagination="true"
                IsStriped="true"
                IsBordered="true"
                AutoGenerateColumns="true"
                ShowSearch="true"
                ShowToolbar="true"
                ShowExtendButtons="true"
                DoubleClickToEdit=true
                ShowColumnList=true
                ShowCardView=true>

             <TableToolbarTemplate>
                 <TableToolbarButton TItem="AspNetUsers" Color="Color.Primary" Text="自由編輯" OnClick="@IsExcelToggle" />
             </TableToolbarTemplate>

         </Table>
     </TabItem>
     <TabItem Text="Roles">
         <Table TItem="AspNetRoles"
                IsPagination="true"
                IsStriped="true"
                IsBordered="true"
                AutoGenerateColumns="true"
                ShowSearch="true"
                ShowToolbar="true"
                ShowExtendButtons="true"
                DoubleClickToEdit=true
                ShowColumnList=true
                ShowCardView=true>

             <TableToolbarTemplate>
                 <TableToolbarButton TItem="AspNetRoles" Color="Color.Primary" Text="自由編輯" OnClick="@IsExcelToggle" />
             </TableToolbarTemplate>

         </Table>
     </TabItem>
     <TabItem Text="Logins">
         <Table TItem="AspNetUserLogins"
                IsPagination="true"
                IsStriped="true"
                IsBordered="true"
                AutoGenerateColumns="true"
                ShowSearch="true"
                ShowToolbar="true"
                ShowExtendButtons="true"
                DoubleClickToEdit=true
                ShowColumnList=true
                ShowCardView=true>

             <TableToolbarTemplate>
                 <TableToolbarButton TItem="AspNetUserLogins" Color="Color.Primary" Text="自由編輯" OnClick="@IsExcelToggle" />
             </TableToolbarTemplate>

         </Table>
     </TabItem>
 </Tab>

元件 DataAdmin.razor 後置程式碼 DataAdmin.razor.cs

using Blazor100.Service;
using BootstrapBlazor.Components;
using Microsoft.AspNetCore.Components;
using System.Diagnostics.CodeAnalysis;

namespace b16blazorIDS2.Pages
{
    public partial class DataAdmin
    {

        [Inject]
        IWebHostEnvironment? HostEnvironment { get; set; }

        [Inject]
        [NotNull]
        NavigationManager? NavigationManager { get; set; }

        [Inject]
        [NotNull]
        ImportExportsService? ImportExportsService { get; set; }

        [Inject]
        [NotNull]
        ToastService? ToastService { get; set; } 
 
        // 由於使用了FreeSql ORM 資料服務,可以直接取物件
        [Inject]
        [NotNull]
        IFreeSql? fsql { get; set; }

        [Inject] ToastService? toastService { get; set; }
        [Inject] SwalService? SwalService { get; set; }


        public bool IsExcel { get; set; }
        public bool DoubleClickToEdit { get; set; } = true;
        protected string UploadPath = "";
        protected string? uploadstatus;
        long maxFileSize = 1024 * 1024 * 15;
        string? tempfilename;
         

        private Task IsExcelToggle()
        {
            IsExcel = !IsExcel;
            DoubleClickToEdit = !IsExcel;
            StateHasChanged();
            return Task.CompletedTask;
        }
 


    }
}

執行截圖

本節原始碼

https://github.com/densen2014/Blazor100/tree/Blazor-教學15-6/b16blazorIDS2

原始碼

https://github.com/densen2014/Blazor100

https://gitee.com/densen2014/Blazor100 (映象/非最新版)