1. 程式人生 > >ASP.NET Core 2.0 MVC項目實戰

ASP.NET Core 2.0 MVC項目實戰

表現層 傳統 long 多層 height rim 基礎架構 blank 控制器

一、前言

畢業後入職現在的公司快有一個月了,公司主要的產品用的是C/S架構,再加上自己現在還在學習維護很老的delphi項目,還是有很多不情願的。之前實習時主要是做.NET的B/S架構的項目,主要還是用的那種傳統的開發模式,只有一個項目用到了Web API,自己負責後端的接口功能實現。既然現在沒辦法改變現狀,那就先改變自己吧。定了個計劃,下班後慢慢的開始學習ASP.NET Core Web API和Vue,準備從前端到後端自己寫一個小項目玩玩,畢竟代碼這個東西,時間長了是會忘的。
嗯,有點扯遠了。這個MVC項目是我的畢業設計,雖然寫的比較爛,而且當時為了趕緊寫完,代碼的冗余程度有點高,但還是希望能給一些準備入門ASP.NET Core MVC的童鞋提供些借鑒吧。代碼我放到Github上了,源碼地址https://github.com/Lanesra712/Danvic.PSU,歡迎大神們拍磚,指出不足處。

二、項目介紹

畢業論文的課題是一個大學生的一個報名系統,主要是為了完成大學生報名過程中的一些數據維護,當然最後因為實在來不及了,好多都沒做。。。項目主要使用到的相關技術如下所示:

  • 項目框架:ASP.NET Core 2.0 MVC
  • ORM:Entity Framework Core(使用Code First)
  • 數據庫引擎:MySQL SERVER 5.7
  • 權限驗證:基於策略的權限驗證(Policy-Based Authorization)
  • 前端框架:AdminLte(一個基於Bootstrap的開源前端UI)
  • 表格控件:Jquery Datatables
  • 數據可視化組件:Echarts
  • 日誌記錄:nlog

三、設計與實現介紹

項目架構采用的是多層架構,通過拆分不同的功能領域,實現各個功能間的相對獨立,項目在VS中搭建完成後如下圖所示。

技術分享圖片

01_Entity:實體層,包含PSU.Entity這一個系統組件,用於存儲數據庫中表所對應的C#對象實體。
02_Infrastructure:基礎架構層,包含PSU.EFCore、PSU.Utility兩個系統組件。PSU.EFCore類庫通過引用Entity Framework Core來完成對於數據庫的操作。PSU.Utility類庫中包含系統開發過程中可能用到的幫助類文件。
03_Logic:邏輯層,包含PSU.Domain、PSU.Repository兩個系統組件。PSU.Domain用於繼承每個領域的接口類庫(PSU.IService),實現領域接口中的功能。PSU.Repository用來實現PSU.Domain類庫中所包含的對於數據庫的操作。
04_Rule:規則層,包含PSU.IService、PSU.Model這兩個系統組件。PSU.IService為系統領域功能接口類庫,PSU.Model為視圖所對應的數據充血模型,對應MVC模式中的實體Model。
Controller.PSU:控制器層,.NET Core類庫,用來存放MVC模式中的各種控制器文件。
PSU.Site:表現層,ASP.NET Core MVC項目,項目主程序。

系統權限驗證設計:
整個系統分為三種角色,分別為管理員、教職工、學生用戶,通過使用Area搭建每個角色的頁面,通過在Controller上添加Area特性,指定當前Controller屬於的角色。在創建用戶時,會指定用戶的角色字段,當用戶登錄成功後,會根據用戶角色進行Claim的創建,通過自定義的AuthorizztionHandler來實現對於當前系統的角色權限控制。
當用戶登錄成功後,會將當前的用戶信息賦值給一個靜態類(使用Session進行存儲),對於判斷用戶是否登錄,則是通過自定義一個控制器的基類,重寫OnActionExecuting方法來實現對於用戶是否登錄的判斷,實現代碼如下。

技術分享圖片
 1 public class DanvicController : Controller
 2 {
 3     /// <summary>
 4     /// 判斷用戶是否登錄
 5     /// </summary>
 6     /// <param name="filterContext"></param>
 7     public override void OnActionExecuting(ActionExecutingContext filterContext)
 8     {
 9         if (CurrentUser.UserId == 0)
10         {
11             string path = filterContext.HttpContext.Request.Path;
12             filterContext.Result = new RedirectResult($"/Secret/Login?ReturnUrl={path}");
13             return;
14         }
15         base.OnActionExecuting(filterContext);
16     }
17 }        
自定義控制器基類 技術分享圖片
 1 public static class CurrentUser
 2 {
 3         #region Initialize
 4 
 5         private static IHttpContextAccessor _httpContextAccessor;
 6 
 7         private static ISession _session => _httpContextAccessor.HttpContext.Session;
 8 
 9         public static void Configure(IHttpContextAccessor httpContextAccessor)
10         {
11             _httpContextAccessor = httpContextAccessor;
12         }
13 
14         #endregion
15 
16         #region Attribute
17 
18         /// <summary>
19         /// 用戶主鍵
20         /// </summary>
21         public static string UserOID
22         {
23             get => _session == null ? "" : _session.GetString("CurrentUser_UserOID");
24             set => _session.SetString("CurrentUser_UserOID", !string.IsNullOrEmpty(value) ? value : "");
25         }
26 
27         /// <summary>
28         ///用戶編號 
29         /// </summary>
30         public static long UserId
31         {
32             get => _session == null ? 0 : Convert.ToInt64(_session.GetString("CurrentUser_UserId"));
33             set => _session.SetString("CurrentUser_UserId", value != 0 ? value.ToString() : "0");
34         }
35 
36         /// <summary>
37         /// 用戶姓名
38         /// </summary>
39         public static string UserName
40         {
41             get => _session == null ? "" : _session.GetString("CurrentUser_UserName");
42             set => _session.SetString("CurrentUser_UserName", !string.IsNullOrEmpty(value) ? value : "");
43         }
44 
45         /// <summary>
46         /// 用戶登錄賬戶
47         /// </summary>
48         public static string UserAccount
49         {
50             get => _session == null ? "" : _session.GetString("CurrentUser_UserAccount");
51             set => _session.SetString("CurrentUser_UserAccount", !string.IsNullOrEmpty(value) ? value : "");
52         }
53 
54         /// <summary>
55         /// 用戶頭像地址
56         /// </summary>
57         public static string UserImage
58         {
59             get => _session == null ? "" : _session.GetString("CurrentUser_UserImage");
60             set => _session.SetString("CurrentUser_UserImage", !string.IsNullOrEmpty(value) ? value : "");
61         }
62 
63         /// <summary>
64         /// 用戶角色
65         /// </summary>
66         public static string UserRole
67         {
68             get => _session == null ? "" : _session.GetString("CurrentUser_UserRole");
69             set => _session.SetString("CurrentUser_UserRole", !string.IsNullOrEmpty(value) ? value : "");
70         }
71 
72         /// <summary>
73         /// 主頁地址
74         /// </summary>
75         public static string UserPage
76         {
77             get => _session == null ? "" : _session.GetString("CurrentUser_UserPage");
78             set => _session.SetString("CurrentUser_UserPage", !string.IsNullOrEmpty(value) ? value : "");
79         }
80 
81         #endregion
82 }    
CurrentUser類

權限驗證代碼如下截圖所示:
控制器示例圖:

技術分享圖片


基於策略的權限驗證實現:

技術分享圖片


自定義驗證Claim:

技術分享圖片

四、總結

接下來我要開始學習ASP.NET Core Web API和Vue了,希望可以保持住,能夠不間斷的在博客上分享自己的學習經歷與見解。當學的差不多的時候,爭取把這個項目精簡,重構,讓自己在成為更好的自己的路途上前進一大步。
因為也是第一次使用ASP.NET Core MVC進行項目的開發,所以遇到了一些自己沒辦法解決的東西,很感謝博客園裏的各位大佬以及一些幫助我的大佬,正是因為有這麽多樂於分享的人在,才能更好的推動.NET Core在國內的生態發展,在寫畢業設計的過程中,參考了很多位博主的博文,真的是很感謝,致敬。

   還是要推廣下自己的個人博客啊,點擊這裏,去看看我的博客啊~~~

項目實現圖如下。

技術分享圖片

技術分享圖片

技術分享圖片

ASP.NET Core 2.0 MVC項目實戰