基于ASP.NET的ToDoList的設計與實現
一、前言
1.1 實驗目的
使學生綜合使用所學過的ASP.NET網絡編程知識,掌握網絡環境程序設計的基本概念;結合實際的操作和設計,鞏固課堂學習內容,掌握網絡環境編程的特點、原理和技術;將理論與實際相結合,應用現有的網絡編程軟件,結合數據庫管理系統軟件,規范、科學地完成一個小型網站的設計與實現。在此基礎上強化學生的實踐意識、提高其實際動手能力和創新能力。
1.2 設備與環境
軟件環境
- ASP.NET Core v3.1
- Mysql v8.x
- VUE v2.x
- Element-UI
- git/github
- NodeJS/npm
- Dotnet
開發環境
- Macbook(蘋果系統)
- vscode(安裝c#插件)
開發環境也可以使用Windows系統,此項目開發時我用的mac環境~
二、項目內容
2.1 項目簡介
基于ASP.NET Core API 和 VUE實現的ToDoList(待辦事項),前后端分離實現(使用RESTFUL規范)
2.2 項目展示
2.3 如何運行此項目
1.下載本項目
下載之后修改todos-Server/DBConnection.cs路徑下的數據庫配置文件,且自行導入sql文件/todos-Server/todoList.sql
2.安裝前端依賴/運行前端
cd todos-fe
npm install # 安裝前端依賴
npm run serve # 運行前端項目
3.安裝服務端依賴
cd todos-Server
dotnet restore # 安裝服務端依賴
dotnet run # 運行服務端項目
三、實驗內容
3.1 數據庫相關
數據表結構
CREATE TABLE `items` (`id` int(11) NOT NULL AUTO_INCREMENT,`title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '待辦事項內容',`createTime` datetime NOT NULL COMMENT '創建時間',`overTime` datetime DEFAULT NULL COMMENT '實際完成時間',`expectTime` datetime DEFAULT NULL COMMENT '預期完成時間',`isComplete` enum('true','false') CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'false' COMMENT '完成狀態',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
數據庫操作代碼單例封裝
詳情代碼參考/todos-Server/DBConnection.cs文件
// 連接數據庫
string connstring ="Server=127.0.0.1;" +"Database=todoList;" +"User ID=root;" +"Password=123456789;";
connection = new MySqlConnection(connstring);
connection.Open();
// 數據庫操作關鍵語句
DBConnection db = DBConnection.Instance ();
if (db.IsConnect ()) { // 連接數據庫try {string sql = "DELETE FROM todoList.items WHERE id=" + id;MySqlCommand cmd = new MySqlCommand (sql, db.Connection);MySqlDataReader rdr = cmd.ExecuteReader ();rdr.Close ();} catch (Exception ex) {Console.WriteLine (ex.ToString ());}
}
3.2 接口Sql語句
新建待辦事項
string sql = "INSERT INTO todoList.items (title,expectTime,createTime) VALUES (\"" +title + "\",\"" +expectTime.ToString ("yyyy-MM-dd HH:mm:ss") + "\",\"" +DateTime.Now.ToString ("yyyy-MM-dd HH:mm:ss") + "\")";Console.WriteLine ("sql is => " + sql);
獲取待辦事項
string sql = "SELECT * FROM todoList.items ORDER BY id DESC LIMIT " + (page - 1) * size + "," + size;
完成事項
string sql = "UPDATE todoList.items SET isComplete=\"true\", overTime=\""+ DateTime.Now.ToString ("yyyy-MM-dd HH:mm:ss") + "\""+ "WHERE id=" + id;
刪除事項
string sql = "DELETE FROM todoList.items WHERE id=" + id;
3.3 難點重點
前后端分離導致的跨域問題
因為瀏覽器出于安全考慮,有同源策略。也就是說,如果協議、域名或者端口有一個不同就是跨域,Ajax 請求會失敗。
那么是出于什么安全考慮才會引入這種機制呢? 其實主要是用來防止 CSRF 攻擊的。簡單點說,CSRF 攻擊是利用用戶的登錄態發起惡意請求。
也就是說,沒有同源策略的情況下,A 網站可以被任意其他來源的 Ajax 訪問到內容。如果你當前 A 網站還存在登錄態,那么對方就可以通過 Ajax 獲得你的任何信息。當然跨域并不能完全阻止 CSRF。
然后我們來考慮一個問題,請求跨域了,那么請求到底發出去沒有? 請求必然是發出去了,但是瀏覽器攔截了響應。你可能會疑問明明通過表單的方式可以發起跨域請求,為什么 Ajax 就不會。因為歸根結底,跨域是為了阻止用戶讀取到另一個域名下的內容,Ajax 可以獲取響應,瀏覽器認為這不安全,所以攔截了響應。但是表單并不會獲取新的內容,所以可以發起跨域請求。同時也說明了跨域并不能完全阻止 CSRF,因為請求畢竟是發出去了。
解決方法: CORS
CORS 需要瀏覽器和后端同時支持。IE 8 和 9 需要通過 XDomainRequest 來實現。
瀏覽器會自動進行 CORS 通信,實現 CORS 通信的關鍵是后端。只要后端實現了 CORS,就實現了跨域。
服務端設置 Access-Control-Allow-Origin 就可以開啟 CORS。 該屬性表示哪些域名可以訪問資源,如果設置通配符則表示所有網站都可以訪問資源。
C#中通過中間件CORS解決,具體代碼如下:
// Startup.cs文件public void ConfigureServices(IServiceCollection services) {services.AddCors(option=>option.AddPolicy("cors", policy => policy.AllowAnyHeader().AllowAnyMethod().AllowCredentials().WithOrigins(new []{"http://127.0.0.1:8080"})));
}public void Configure() {app.UseCors("cors");
}
雖然設置 CORS 和前端沒什么關系,但是通過這種方式解決跨域問題的話,會在發送請求時出現兩種情況,分別為簡單請求和復雜請求。
簡單請求
以 Ajax 為例,當滿足以下條件時,會觸發簡單請求
使用下列方法之一:
- GET
- HEAD
- POST
Content-Type 的值僅限于下列三者之一:
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
請求中的任意 XMLHttpRequestUpload 對象均沒有注冊任何事件監聽器; XMLHttpRequestUpload 對象可以使用 XMLHttpRequest.upload 屬性訪問。
復雜請求
那么很顯然,不符合以上條件的請求就肯定是復雜請求了。
對于復雜請求來說,首先會發起一個預檢請求,該請求是 option 方法的,通過該請求來知道服務端是否允許跨域請求。
數據列表分頁
// 服務端使用sql的limit語法進行分頁處理
string sql = "SELECT * FROM todoList.items ORDER BY id DESC LIMIT " + (page - 1) * size + "," + size;
// sql is => SELECT * FROM todoList.items ORDER BY id DESC LIMIT 0,20
api接口獲取列表時傳入page和pageSize
分頁api
前端使用分頁組件
服務端返回實例
{"sum": 3,"list": [{"id": 3,"title": "完成前端內容","isComplete": false,"createTime": "2019-12-24T16:31:39","overTime": null,"expectTime": "2019-12-24T14:31:30"},// ...]
}
四、實驗感悟
經過兩周的ASP.NET課程設計,學習了csharp編寫服務端代碼,更加深入理解了語言的想通性,ASP.NET和NodeJS中有很多相似的概念,比如中間件,控制器,模型等。經過學習C#,感受到了C#作為一門優秀的靜態類型語言相比于JavaScript的強勢優點,更完善的代碼提示和函數跳轉等,感受到了JS轉typeScript的必要性,使用靜態類型語言可以減少代碼編寫過程中由于粗心造成的BUG,減少拍錯時間等。還有,這次課設和同學交流了一些,強烈建議學校課設能使用git工具進行項目管理,從大一到大四,課設皆通過github托管,到大四的時候,將收獲頗多。計算機系的課設文檔也建議由word轉向markdown編寫,能很快的提高效率,并且markdown是畢業工作之后的必備能力之一。