:::info - **.Net Core version:** v3.1.101 - **AdminLTE version:** v3.0.1 - **OS:** Ubuntu 18.04 - **Editor:** Visual Studio Code ::: # AdminLTE with .Net Core 3.1(編修中) 本教學將分別介紹資料庫搭建、.Net Core搭配AdminLTE建立管理者後台(Dashboard)。 ## 將AdminLTE版型利用 .Net Core搭建 ### 新增MVC專案 ``` dotnet new mvc -o "專案名稱" ``` ### 使用Libman作為套件管理員 詳細使用方法請參酌[libman使用網頁](https://docs.microsoft.com/zh-tw/aspnet/core/client-side/libman/libman-cli?view=aspnetcore-3.1) #### 初始化Libman 在專案資料夾使用libman ``` libman init ``` 此時,會出現以下訊息: ``` DefaultProvider [cdnjs]: ``` 此訊息主要是針對Library的提供方做確認,預設為cdnjs,因此按下Enter進行下一步。完成後會於專案資料夾內看到"libman.json"的檔案。 #### 專案中會使用到的Library * font-awesome * iCheck * layer * jquery-cookie * ionicons * Chart.js * datatables ##### 利用Libman安裝Library 使用libman CLI安裝套件,通常MVC的lib都會安裝在 ``` ~/wwwroot/lib/"套件名稱" ``` 所以在使用libman安裝套件的方法為 ``` libman install <LIBRARY> -d wwwroot/lib/<LIBRARY> ``` 也可以直接編寫libman.json檔案,新增完後,請restore檔案 ``` libman restore ``` ### 下載AdminLTE版型 :::success 下載AdminLTE版型穩定版。<[下載](https://github.com/ColorlibHQ/AdminLTE/releases)> ::: #### 將下載的檔案解壓縮 ![](https://i.imgur.com/3QBoor4.png) #### 將dist資料夾中的css,img,js移到專案中的wwwroot相對應的資料夾下 ![](https://i.imgur.com/vki2Umy.png) --> ![](https://i.imgur.com/qY1nZ7J.png) ### 建立Layout版型 #### 修改View:arrow_right:Shared:arrow_right:_Layout.cshtml ```=cshtml <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>AdminLTE 3 | Calendar</title> <!-- Tell the browser to be responsive to screen width --> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Font Awesome --> <link rel="stylesheet" href="~/lib/font-awesome/css/all.min.css"> <!-- Ionicons --> <link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css"> <!-- Theme style --> <link rel="stylesheet" href="~/css/adminlte.min.css"> <!-- Google Font: Source Sans Pro --> <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700" rel="stylesheet"> </head> <body class="hold-transition sidebar-mini layout-fixed"> <div class="wrapper"> <!-- Navbar --> <nav class="main-header navbar navbar-expand navbar-white navbar-light"> <!-- Left navbar links --> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link" data-widget="pushmenu" href="#" role="button"><i class="fas fa-bars"></i></a> </li> <li class="nav-item d-none d-sm-inline-block"> <a href="index3.html" class="nav-link">Home</a> </li> <li class="nav-item d-none d-sm-inline-block"> <a href="#" class="nav-link">Contact</a> </li> </ul> <!-- Right navbar links --> <ul class="navbar-nav ml-auto"> <!-- Messages Dropdown Menu --> <li class="nav-item dropdown"> <a class="nav-link" data-toggle="dropdown" href="#"> <i class="far fa-comments"></i> <span class="badge badge-danger navbar-badge">3</span> </a> <div class="dropdown-menu dropdown-menu-lg dropdown-menu-right"> <a href="#" class="dropdown-item"> <!-- Message Start --> <div class="media"> <img src="~/images/user1-128x128.jpg" alt="User Avatar" class="img-size-50 mr-3 img-circle"> <div class="media-body"> <h3 class="dropdown-item-title"> Brad Diesel <span class="float-right text-sm text-danger"><i class="fas fa-star"></i></span> </h3> <p class="text-sm">Call me whenever you can...</p> <p class="text-sm text-muted"><i class="far fa-clock mr-1"></i> 4 Hours Ago</p> </div> </div> <!-- Message End --> </a> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item"> <!-- Message Start --> <div class="media"> <img src="~/images/user8-128x128.jpg" alt="User Avatar" class="img-size-50 img-circle mr-3"> <div class="media-body"> <h3 class="dropdown-item-title"> John Pierce <span class="float-right text-sm text-muted"><i class="fas fa-star"></i></span> </h3> <p class="text-sm">I got your message bro</p> <p class="text-sm text-muted"><i class="far fa-clock mr-1"></i> 4 Hours Ago</p> </div> </div> <!-- Message End --> </a> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item"> <!-- Message Start --> <div class="media"> <img src="~/images/user3-128x128.jpg" alt="User Avatar" class="img-size-50 img-circle mr-3"> <div class="media-body"> <h3 class="dropdown-item-title"> Nora Silvester <span class="float-right text-sm text-warning"><i class="fas fa-star"></i></span> </h3> <p class="text-sm">The subject goes here</p> <p class="text-sm text-muted"><i class="far fa-clock mr-1"></i> 4 Hours Ago</p> </div> </div> <!-- Message End --> </a> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item dropdown-footer">See All Messages</a> </div> </li> <!-- Notifications Dropdown Menu --> <li class="nav-item dropdown"> <a class="nav-link" data-toggle="dropdown" href="#"> <i class="far fa-bell"></i> <span class="badge badge-warning navbar-badge">15</span> </a> <div class="dropdown-menu dropdown-menu-lg dropdown-menu-right"> <span class="dropdown-item dropdown-header">15 Notifications</span> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item"> <i class="fas fa-envelope mr-2"></i> 4 new messages <span class="float-right text-muted text-sm">3 mins</span> </a> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item"> <i class="fas fa-users mr-2"></i> 8 friend requests <span class="float-right text-muted text-sm">12 hours</span> </a> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item"> <i class="fas fa-file mr-2"></i> 3 new reports <span class="float-right text-muted text-sm">2 days</span> </a> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item dropdown-footer">See All Notifications</a> </div> </li> <li class="nav-item"> <a class="nav-link" data-widget="control-sidebar" data-slide="true" href="#" role="button"> <i class="fas fa-th-large"></i> </a> </li> </ul> </nav> <!-- /.navbar --> <!-- Main Sidebar Container --> <aside class="main-sidebar sidebar-dark-primary elevation-4"> <!-- Brand Logo --> <a href="index3.html" class="brand-link"> <img src="~/images/AdminLTELogo.png" alt="AdminLTE Logo" class="brand-image img-circle elevation-3" style="opacity: .8"> <span class="brand-text font-weight-light">AdminLTE 3</span> </a> <!-- Sidebar --> <div class="sidebar"> <!-- Sidebar user panel (optional) --> <div class="user-panel mt-3 pb-3 mb-3 d-flex"> <div class="image"> <img src="~/images/user2-160x160.jpg" class="img-circle elevation-2" alt="User Image"> </div> <div class="info"> <a href="#" class="d-block">Alexander Pierce</a> </div> </div> <!-- Sidebar Menu --> <nav class="mt-2"> <ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false"> <!-- Add icons to the links using the .nav-icon class with font-awesome or any other icon font library --> @* <li class="nav-item has-treeview menu-open"> <a href="#" class="nav-link active"> <i class="nav-icon fas fa-tachometer-alt"></i> <p> Dashboard <i class="right fas fa-angle-left"></i> </p> </a> <ul class="nav nav-treeview"> <li class="nav-item"> <a href="./index.html" class="nav-link active"> <i class="far fa-circle nav-icon"></i> <p>Dashboard v1</p> </a> </li> <li class="nav-item"> <a href="./index2.html" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Dashboard v2</p> </a> </li> <li class="nav-item"> <a href="./index3.html" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Dashboard v3</p> </a> </li> </ul> </li> *@ <li class="nav-item"> <a href="/home" class="nav-link"> <i class="nav-icon fas fa-tachometer-alt"></i> <p> Dashboard </p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="nav-icon fas fa-th"></i> <p> Widgets <span class="right badge badge-danger">New</span> </p> </a> </li> <li class="nav-item has-treeview"> <a href="#" class="nav-link"> <i class="nav-icon fas fa-copy"></i> <p> Layout Options <i class="fas fa-angle-left right"></i> <span class="badge badge-info right">6</span> </p> </a> <ul class="nav nav-treeview"> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Top Navigation</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Top Navigation + Sidebar</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Boxed</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Fixed Sidebar</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Fixed Navbar</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Fixed Footer</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Collapsed Sidebar</p> </a> </li> </ul> </li> <li class="nav-item has-treeview"> <a href="#" class="nav-link"> <i class="nav-icon fas fa-chart-pie"></i> <p> Charts <i class="right fas fa-angle-left"></i> </p> </a> <ul class="nav nav-treeview"> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>ChartJS</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Flot</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Inline</p> </a> </li> </ul> </li> <li class="nav-item has-treeview"> <a href="#" class="nav-link"> <i class="nav-icon fas fa-tree"></i> <p> UI Elements <i class="fas fa-angle-left right"></i> </p> </a> <ul class="nav nav-treeview"> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>General</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Icons</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Buttons</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Sliders</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Modals & Alerts</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Navbar & Tabs</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Timeline</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Ribbons</p> </a> </li> </ul> </li> <li class="nav-item has-treeview"> <a href="#" class="nav-link"> <i class="nav-icon fas fa-edit"></i> <p> Forms <i class="fas fa-angle-left right"></i> </p> </a> <ul class="nav nav-treeview"> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>General Elements</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Advanced Elements</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Editors</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Validation</p> </a> </li> </ul> </li> <li class="nav-item has-treeview"> <a href="#" class="nav-link"> <i class="nav-icon fas fa-table"></i> <p> Tables <i class="fas fa-angle-left right"></i> </p> </a> <ul class="nav nav-treeview"> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>Simple Tables</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>DataTables</p> </a> </li> <li class="nav-item"> <a href="#" class="nav-link"> <i class="far fa-circle nav-icon"></i> <p>jsGrid</p> </a> </li> </ul> </li> </ul> </nav> <!-- /.sidebar-menu --> </div> <!-- /.sidebar --> </aside> <!-- Content Wrapper. Contains page content --> <div class="content-wrapper"> @RenderBody() </div> <!-- /.content-wrapper --> <footer class="main-footer"> <strong>Copyright &copy; 2014-2019 <a href="http://adminlte.io">AdminLTE.io</a>.</strong> All rights reserved. <div class="float-right d-none d-sm-inline-block"> <b>Version</b> 3.0.5 </div> </footer> <!-- Control Sidebar --> <aside class="control-sidebar control-sidebar-dark"> <!-- Control sidebar content goes here --> </aside> <!-- /.control-sidebar --> </div> <!-- ./wrapper --> <environment include="Development"> <!-- REQUIRED JS SCRIPTS --> <!-- jQuery 3 --> <script src="~/lib/jquery/dist/jquery.min.js"></script> <!-- Bootstrap 3.3.7 --> <script src="~/lib/bootstrap/dist/js/bootstrap.min.js"></script> <!-- AdminLTE App --> <script src="~/js/adminlte.min.js"></script> <!-- Optionally, you can add Slimscroll and FastClick lib. Both of these lib are recommended to enhance the user experience. --> <!-- AdminLTE dashboard demo (This is only for demo purposes) --> <script src="~/js/pages/dashboard.js"></script> <!-- AdminLTE for demo purposes --> <script src="~/js/demo.js"></script> </environment> </body> </html> ``` ## 動態驗證登入頁面設計 :::success 在許多場域中,存在著管理者、使用者等不同的權限設計,在此會進行動態驗證登入的教學。 所需相關工具或技能: - [X] MySQL - [X] HTML - [X] .Net Core ::: ### 資料庫設計 我們將在資料庫(DB)中新增四個表(Table) - **User:** 使用者帳號及密碼儲存的資料表 - **Roles:** 規則資料表,主要區分出權限的表 - **Menus:** 選單資料表,將選單存在資料庫中,根據權限不同,會動態顯示不同的選單 - **Link_roles_menus:** 將權限與選單進行連結的表 #### 創建User的表 ```=mysql CREATE TABLE `adminlte_test`.`User` ( `id` INT NOT NULL AUTO_INCREMENT , `account` VARCHAR(255) NOT NULL , `password` VARCHAR(255) NOT NULL , `roles_id` INT NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB; ``` #### 創建Roles的表 ```=mysql CREATE TABLE `adminlte_test`.`Roles` ( `id` INT NOT NULL AUTO_INCREMENT , `title` VARCHAR(255) NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB; ``` #### 創建Menus的表 ```=mysql CREATE TABLE `adminlte_test`.`Menus` ( `id` INT NOT NULL AUTO_INCREMENT , `name` VARCHAR(255) NOT NULL , `icon` VARCHAR(50) NOT NULL , `url` VARCHAR(255) NULL , `parent_id` INT NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB; ``` #### 創建Link_roles_menus的表 ```=mysql CREATE TABLE `adminlte_test`.`Link_roles_menus` ( `id` INT NOT NULL AUTO_INCREMENT , `roles_id` INT NOT NULL , `menus_id` INT NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB; ``` #### 建立關聯 ```=mysql ALTER TABLE `Link_roles_menus` ADD CONSTRAINT `link_roles_menus_ibfk_1` FOREIGN KEY (`menus_id`) REFERENCES `Menus`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT; ALTER TABLE `Link_roles_menus` ADD CONSTRAINT `link_roles_menus_ibfk_2` FOREIGN KEY (`roles_id`) REFERENCES `Roles`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT; ALTER TABLE `User` ADD CONSTRAINT `user_ibfk_1` FOREIGN KEY (`roles_id`) REFERENCES `Roles`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT; ``` 在MVC專案中使用libman套件管理員 [libman使用網頁](https://docs.microsoft.com/zh-tw/aspnet/core/client-side/libman/libman-cli?view=aspnetcore-3.1) 安裝 LibMan CLI:`dotnet tool install -g Microsoft.Web.LibraryManager.Cli` 在Startup.cs改為以下 ```C#= 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; namespace <專案名稱> { 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.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30);//We set Time here options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); services.AddHttpContextAccessor(); services.AddControllersWithViews(); } // 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("/Home/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.UseSession(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Login}/{action=Index}/{id?}"); }); } } } ``` 安裝以下套件 ```=dotnet dotnet tool install --global dotnet-ef dotnet add package Microsoft.EntityFrameworkCore.Tools.DotNet --version 2.0.3 dotnet add package Microsoft.EntityFrameworkCore.Design --version 3.1.1 ``` 加入Pomelo ```=dotnet dotnet add package Pomelo.EntityFrameworkCore.MySql ``` 安裝完後 ```=dotnet dotnet restore ``` 將專案連結資料庫 ```=dotnet dotnet ef dbcontext scaffold "Server=localhost;User Id=test;Password=p@ssw0rd;Database=test" "Pomelo.EntityFrameworkCore.MySql" -c MyDbContext -o Models ``` ## Reference 參考這個[網站](https://codinginfinite.com/login-page-asp-net-core-mvc-database/) 和這個[網站](https://www.cnblogs.com/fonour/p/5862369.html) 記得注意dotnet core 的版本