[ASP.NET MVC] 前台會員註冊範例教學 #CH1
在學習 C# 與資料庫的互動方式,有一個常見且實用的教學就是會員登入、註冊與修改會員資料等範例,學習過程中會用到資料庫新增、修改與查詢動作,是理解程式與資料庫互動的常見程式碼。
當學會了這個範例,將來為客戶開發系統的時候,就可以派上用場。
此篇文章主要以 ASP.NET MVC 為核心,前端使用 Vue.js 框架,而後端使用 SQL Server 當資料庫。
Vue.js 是前端 3 大主流框架的其中之一,目標是透過簡單的 API 提供開發者實作資料綁定與操作網頁上的元件,Vue.js 的核心把焦點關注在狀態與畫面的同步層級上,適合與其他 Javascript 函式庫整合,同時也適合當作 ASP.NET MVC 的前端框架。
SQL Server 是微軟推出的關聯式資料庫,使用 SQL 語言就可以輕鬆操作資料庫。
編寫此教學文章是為了幫助更多新加入的軟體工程師們,有更簡單實用的範例,可以快速學習程式語言。
這次我將會簡化這個基礎必學的前端會員範例,適合剛接觸 C# 與資料庫程式的新手學習。
文末有提供此操作範例的完整程式碼下載,有需要可以自行下載瀏覽。
Contents
建立新 MVC 專案
尚未安裝 Visual Studio 2022 的話,請先參考此文章安裝:微軟整合開發工具 Visual Studio 2022 安裝教學。
開啟 Visual Studio 2022 選擇「建立新專案」,專案類型為「ASP.NET Web 應用程式(.NET Framework)」。
輸入專案名稱及儲存位置。
選擇「MVC」類型。
完成後即會開啟 MVC 的範本專案,執行「F5」,可以瀏覽範本初始畫面。
調整 MVC 範本 – 佈局頁
打開 \Views\Shared\_Layout.cshtml 頁面。
引用 Vue.js 底層元件
在 Vue.js 官方教學找到 CDN 網址。
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
在 @Scripts.Render("~/bundles/bootstrap")
語法下面,加入 Vue.js 底層元件。
增加註冊及登入選單
打開佈局頁 Views\Shared\_Layout.cshtml,在原有的選單後面增加 2 個新連結。
1 2 |
<li>@Html.ActionLink("註冊", "Register", "Member")</li> <li>@Html.ActionLink("登入", "Login", "Member")</li> |
增加新 Controller – MemberController
我們將所有處理會員的頁面及邏輯都放在 MemberController 裡面。
在「Controllers」按右鍵,新增一個「控制器」。
加入「MVC 5 控制器-空白」,取名為「MemberController」。
增加註冊頁面 Action
在 MemberController 頁面增加一個回傳 Register 的 View 頁面。
增加註冊頁面 View
在 Register() 語法上按右鍵選「新增檢視」。
選擇「MVC 5 檢視」加入,確認名稱為 “Register”,有勾選「使用版面配置頁」。
新增之後在 Views\Member\Register.cshtml 會新增 View 檢視頁面。
編寫註冊 View 語法
因為 VS 在 MVC 的專案,預設加入了 jQuery 及 Bootstrap 的元件,所以我們可以直接使用 Bootstrap 語法來設計畫面。
我直接在 Bootstrap 3 的官方說明文件,取一些表單語法來用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<div class="panel panel-primary"> <div class="panel-heading">註冊頁面範例</div> <div class="panel-body"> <div class="form-group"> <label>帳號</label> <input type="text" class="form-control"> </div> <div class="form-group"> <label>密碼</label> <input type="password" class="form-control"> </div> <div class="form-group"> <label>姓名</label> <input type="text" class="form-control"> </div> <div class="form-group"> <label>EMail</label> <input type="text" class="form-control"> </div> </div> <div class="panel-footer"> <button type="button" class="btn btn-primary">註冊</button> </div> </div> |
在 Views\Member\Register.cshtml 增加這些語法後,按 F5 執行專案,切換到「註冊」頁,畫面就會出現輸入表單。
這裡只是純顯示 Html 而已,還沒加上邏輯。
加入 Vue.js 控制元件
我們在前面 _Layout.cshtml 已經加了 Vue.js 的底層元件,所以這註冊頁面,就可以套用 Vue.js 的寫法。
我將剛剛的 HTML 修改一下,加入了 Vue.js 語法,並增加 DoRegister() 的方法,執行註冊時傳送表單到 Controller 頁面。
以下程式碼可以整個取代 Register.cshtml 內容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
<div id="VuePage"> <!--使用 Bootstrap 設計註冊表單--> <div class="panel panel-primary"> <div class="panel-heading">註冊頁面範例</div> <div class="panel-body"> <div class="form-group"> <label>帳號</label> <input type="text" class="form-control" v-model="form.UserID"> </div> <div class="form-group"> <label>密碼</label> <input type="password" class="form-control" v-model="form.UserPwd"> </div> <div class="form-group"> <label>姓名</label> <input type="text" class="form-control" v-model="form.UserName"> </div> <div class="form-group"> <label>EMail</label> <input type="text" class="form-control" v-model="form.UserEmail"> </div> </div> <div class="panel-footer"> <button type="button" class="btn btn-primary" v-on:click="DoRegister()">註冊</button> </div> </div> <!--使用 Bootstrap Modal 樣式,當執行有錯誤時,顯示錯誤訊息--> <div class="modal fade" id="ErrorAlert" tabindex="-1" role="dialog"> <div class="modal-dialog modal-lg" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> <h4 class="modal-title">錯誤訊息</h4> </div> <div class="modal-body" id="ErrorMsg" style="overflow-x:auto;width:100%;"> </div> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal --> </div> @section scripts { <script> var VuePage = new Vue({ el: '#VuePage' , data: function () { var data = { form: {} }; return data; } , methods: { // 執行註冊按鈕 DoRegister: function () { var self = this; // 組合表單資料 var postData = {}; postData['UserID'] = self.form.UserID; postData['UserPwd'] = self.form.UserPwd; postData['UserName'] = self.form.UserName; postData['UserEmail'] = self.form.UserEmail; // 使用 jQuery Ajax 傳送至後端 $.ajax({ url:'@Url.Content("~/Member/DoRegister")', method:'POST', dataType:'json', data: { inModel: postData }, success: function (datas) { if (datas.ErrMsg) { alert(datas.ErrMsg); return; } alert(datas.ResultMsg); }, error: function (err) { $('#ErrorMsg').html(err.responseText); $('#ErrorAlert').modal('toggle'); }, }); } } }) </script> } |
Vue.js 可取得網頁上的欄位資料,將資料利用 Ajax 傳送到後端。
var postData
主要在建立傳送表單,將 4 個欄位資料放進表單裡面,向後端傳送。
向後端傳送資料使用的是 jQuery.ajax() 方法,方法內指定要傳送的網址 (url)、Http 協定(method)、資料型別 (dataType)、資料內容 (data)、成功回傳方法 (success)、失敗回傳方法 (error)。
關於 Vue.js 的教學語法,可以到官網上面查詢,官網有完整的教學。
編寫註冊 Controller 語法
剛剛在 View 會傳送一個動作呼叫 Member/DoRegister
所以在 MemberController 需要建立回應的方法。
開啟 \Controllers\MemberController.cs,然後加入以下 Action:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
/// <summary> /// 執行註冊 /// </summary> /// <param name="inModel"></param> /// <returns></returns> public ActionResult DoRegister(DoRegisterIn inModel) { DoRegisterOut outModel = new DoRegisterOut(); if (string.IsNullOrEmpty(inModel.UserID) || string.IsNullOrEmpty(inModel.UserPwd) || string.IsNullOrEmpty(inModel.UserName) || string.IsNullOrEmpty(inModel.UserEmail)) { outModel.ErrMsg = "請輸入資料"; } else { SqlConnection conn = null; try { // 資料庫連線 string connStr = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["ConnDB"].ConnectionString; conn = new SqlConnection(); conn.ConnectionString = connStr; conn.Open(); // 檢查帳號是否存在 string sql = "select * from Member where UserID = @UserID"; SqlCommand cmd = new SqlCommand(); cmd.CommandText = sql; cmd.Connection = conn; // 使用參數化填值 cmd.Parameters.AddWithValue("@UserID", inModel.UserID); // 執行資料庫查詢動作 DbDataAdapter adpt = new SqlDataAdapter(); adpt.SelectCommand = cmd; DataSet ds = new DataSet(); adpt.Fill(ds); if (ds.Tables[0].Rows.Count > 0) { outModel.ErrMsg = "此登入帳號已存在"; } else { // 將密碼使用 SHA256 雜湊運算(不可逆) string salt = inModel.UserID.Substring(0, 1).ToLower(); //使用帳號前一碼當作密碼鹽 SHA256 sha256 = SHA256.Create(); byte[] bytes = Encoding.UTF8.GetBytes(salt + inModel.UserPwd); //將密碼鹽及原密碼組合 byte[] hash = sha256.ComputeHash(bytes); StringBuilder result = new StringBuilder(); for (int i = 0; i < hash.Length; i++) { result.Append(hash[i].ToString("X2")); } string NewPwd = result.ToString(); // 雜湊運算後密碼 // 註冊資料新增至資料庫 sql = @"INSERT INTO Member (UserID,UserPwd,UserName,UserEmail) VALUES (@UserID, @UserPwd, @UserName, @UserEmail)"; cmd = new SqlCommand(); cmd.Connection = conn; cmd.CommandText = sql; // 使用參數化填值 cmd.Parameters.AddWithValue("@UserID", inModel.UserID); cmd.Parameters.AddWithValue("@UserPwd", NewPwd); // 雜湊運算後密碼 cmd.Parameters.AddWithValue("@UserName", inModel.UserName); cmd.Parameters.AddWithValue("@UserEmail", inModel.UserEmail); // 執行資料庫更新動作 cmd.ExecuteNonQuery(); outModel.ResultMsg = "註冊完成"; } } catch (Exception ex) { throw ex; } finally { if (conn != null) { //關閉資料庫連線 conn.Close(); conn.Dispose(); } } } // 輸出json return Json(outModel); } |
這是我習慣的回應寫法,將傳入的來源宣告為 DoRegisterIn
物件,將要回傳的物件宣告為DoRegisterOut
。
命名方式為方法名稱的後面增加 In 及 Out 表示資料方向,回傳的格式一律為 Json 格式。
DoRegisterIn
與 DoRegisterOut
都是新類別,會在 Model 裡面新增。
在方法內主要是連線資料庫,檢查帳號是否存在,當不存在時,才會寫入一筆資料進資料庫。
在產生儲存密碼時,我使用了 SHA256 雜湊運算 + 密碼鹽的處理,提高了密碼保存的安全性,
有關密碼鹽的知識,可以參考維基百科說明。
密碼儲存觀念
有關使用者重要的密碼儲存在資料庫的時候,建議使用不可逆的雜湊運算,例如 SHA256,在產生儲存密碼時,建議加入密碼鹽來混淆原密碼泄漏風險。
若使用者忘記密碼時,可以採用身份驗證後,直接更換使用者密碼。
設定資料庫連線字串
剛剛在連線資料庫的語法中使用到
System.Web.Configuration.WebConfigurationManager.ConnectionStrings["ConnDB"].ConnectionString;
這指的是連線字串由 Web.config 中取出 connectionStrings 名稱為 “ConnDB” 的連線字串,
接下來就開啟專案根目錄下的「Web.config」,設定資料庫連線字串。
在 <configuration></configuration> 範圍內加入語法:
1 2 3 |
<connectionStrings> <add name="ConnDB" connectionString="Data Source=127.0.0.1;Initial Catalog=Teach;Persist Security Info=false;User ID=test;Password=test;" providerName="System.Data.SqlClient"/> </connectionStrings> |
連線字串的參數需改成你們的環境,參數為:
Data Source=資料庫主機名稱或位址
Initial Catalog=資料庫名稱
User ID=帳號
Password=密碼
增加註冊 Model
剛剛在 MemberController 宣告的 DoRegisterIn 及 DoRegisterOut 都是新物件名稱,所以還需要在 Model 建立類別。
要加入一個新 Model 的方法是在「Models」按右鍵選「加入 > 類別」。
選擇「類別」,輸入與 Controller 同名的 “MemberModel”,執行「新增」加入類別。
在 MemberModel 的類別內加入 DoRegisterIn 及 DoRegisterOut 兩個新類別。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/// <summary> /// 註冊參數 /// </summary> public class DoRegisterIn { public string UserID { get; set; } public string UserPwd { get; set; } public string UserName { get; set; } public string UserEmail { get; set; } } /// <summary> /// 註冊回傳 /// </summary> public class DoRegisterOut { public string ErrMsg { get; set; } public string ResultMsg { get; set; } } |
DoRegisterIn
定義由 View 會傳入的欄位名稱,DoRegisterOut
則定義 Controller 處理完之後,會回傳給 View 的欄位名稱。
我對於 Model 的使用目的,均為定義 Controller 與 View 之間的傳遞欄位型別。
新增資料庫與資料表
我使用的資料庫是 SQL Server 2019,尚未安裝的朋友可以參考這篇文章先安裝:如何安裝 SQL Server 2019 免費開發版。
安裝之後,使用 SSMS 登入,在檔案總管的「資料庫」按右鍵可以新增一個資料庫。
我在本機新建一個 “Teach” 的資料庫,然後使用語法新增一個 “Member” 的資料表。
1 2 3 4 5 6 7 8 9 10 |
CREATE TABLE [dbo].[Member]( [UserID] [varchar](10) NOT NULL, [UserPwd] [varchar](64) NOT NULL, [UserName] [nvarchar](20) NOT NULL, [UserEmail] [varchar](50) NOT NULL, CONSTRAINT [PK_Member] PRIMARY KEY CLUSTERED ( [UserID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] |
這是要儲存網頁的註冊資料。
測試範例
完成程式碼及資料庫後,就可以執行「F5」運行專案。
切換至「註冊」範例,輸入資料後,執行「註冊」功能。
確認畫面出現「註冊完成」後,就可以檢查資料庫。
使用 SSMS 登入資料庫,檢查 Member 的資料,
就可以看到剛剛在畫面上新增的資料了。
重點整理
- MVC 為專案核心,Vue.js 處理前端控制,SQL Server 處理資料儲存
- 調整佈局頁 Javascript 位置、加入 Vue.js 底層
- 使用 Bootstrap 樣式可快速製作美觀的表單
- 使用 Vue.js 可取得網頁上的欄位資料,將資料利用 Ajax 傳送到後端
- Controller 語法與資料庫連線,執行查詢與新增動作
- Model 定義 Controller 與 View 之間的傳遞欄位型別
- 建立資料庫,執行範例
範例下載
此範例包含完整範例內容,連結 GitHub 下載範例
推薦課程
下一篇教學文章
相關學習文章
- [ASP.NET] 如何串接 Google Api 帳戶登入
- [ASP.NET MVC] 取得 Request 常用資訊 (IP, 作業系統, 瀏覽器, 呼叫網址)
- [Bootstrap + Vue.js + ASP.NET MVC] 增加欄位修改過程紀錄
如果你在學習上有不懂的地方,需要諮詢服務,可以參考站長服務,我想辨法解決你的問題
如果文章內容有過時、不適用或錯誤的地方,幫我在下方留言通知我一下,謝謝
連線字串寫在controller ?
“在這裡我想跟你分享如何成為一位稱職的軟體工程師” <– 你認真的嗎
為了簡化示範教學,我才直接放在 Controller 裡面
但想了一下 還是以正規的做法教學好了
我已修改程式碼了
謝謝你的建議與提醒
不好意思想請教一下,目前上面教學都是一步一步地照做,不過在最後執行時打完註冊資料出現錯誤訊息如下:
“描述: HTTP 404. 您要尋找的資源 (或其相依性的其中之一) 可能已經移除、名稱已經變更或是暫時無法使用。請檢閱下列 URL,並且確定它的拼寫無誤。
要求的 URL: /Member/DoRegister”
這樣是我哪裡有做錯嗎? 謝謝!
這可能是 View 的 Ajax 要呼叫的 Controller 的路徑有錯,你檢查 Controller 名稱是否正確
我確認過,View當中的Register.cshtml內容跟您應該是一樣的,還是問題不是出在這裡?
順便想問一下,您所說要呼叫的Controller是DoRegisterController嗎?
不是 DoRegisterController 喔
正確是在 MemberController 才對,而 MemberController 裡面有一個 Action 叫做 DoRegister
不好意思再次打擾,我已將DoRegister放進MemberController了,執行之後我將資料全部輸入完按下註冊時,在DoRegister中會出現:
System.Data.SqlClient.SqlException: ‘使用者 ‘test’ 的登入失敗。’
的錯誤訊息在Catch中,想再請教您了,謝謝!
不好意思,想再請教一下,我已經照您說的將DoRegister放入MemberController中,執行之後輸入資料按下註冊鈕的時候會出現:
System.Data.SqlClient.SqlException: ‘使用者 ‘test’ 的登入失敗。在catch區塊的地方,想詢問一下這可能是什麼原因,謝謝
因為我範例的資料庫連線跟你的資料庫連線不一樣,我預設是本機 127.0.0.1,資料庫名稱是: Teach,帳號: test,密碼: test
而你的帳密跟我不一樣,就會有帳密錯誤的問題,可能你的資料庫名稱也跟我不一樣,都要修改
我將資料庫名稱及密碼改為跟您一樣的已經成功運作了,不過想問最後一個問題,如果今天想要使用跟您不同的帳號密碼登入的話,在VS這邊我要從哪邊去改? 謝謝
你打開 Web.config 裡面就可以設定了喔
Data Source=127.0.0.1;Initial Catalog=Teach;Persist Security Info=false;User ID=test;Password=test;
這一行是設定資料庫連線,你改一下就可以了喔
成功了! 謝謝您的幫忙
不好意思請問一下,我的在按註冊完後跑出這個錯誤
System.NullReferenceException: 並未將物件參考設定為物件的執行個體
前面都是照做,是出了甚麼問題呢?
這是在後端的 C# 出現 Null 問題,你使用 Debug 應該會指向有問題的行數,你看一下是否該物件為什麼為 Null
您好,想請問一下,我也是一步一步照著做,不過在最後執行時打完註冊資料出現錯誤訊息如下:
找不到資源。
描述: HTTP 404. 您要尋找的資源 (或其相依性的其中之一) 可能已經移除、名稱已經變更或是暫時無法使用。請檢閱下列 URL,並且確定它的拼寫無誤。
要求的 URL: /Member/Contact
請問我是一樣依照前面那位Sean的步驟去除錯嗎
出現 /Member/Contact 應該是在前端 View 的 Ajax 的網址有錯誤,你檢查一下
我範例是 url:’@Url.Content(“~/Member/DoRegister”)’,
你檢查一下是否相同
您好,想請問一下,我也是一步一步照著做,在最後輸入完帳號、密碼、姓名 跟 emai之後,跳出錯誤訊息,不好意思請問這要怎麼除錯,感謝
您好,想請問一下,我也是一步一步照著做,在最後輸入完帳號、密碼、姓名 跟 emai之後,按註冊,跳出請輸入資料的訊息,想請問一下要怎麼除錯,不好意思
私訊幫你看一下
請問一下,你的格式是怎麼設計及定義的?我有嘗試在程式中套用其他模板(目前只用在首頁),功能都沒問題,但格式會跑掉,尤其是layout裡的登入註冊按鈕,如果用你的定義,按鈕會找不到,但如果不用的話,所有頁面的格式就都會跑掉。可以的話想請教你如何修改
你說的格式是那部份?
感覺你的問題在基礎的 HTML 排版問題,還是你要先下載整個範本,然後試著比對一下我的和你的差異,這樣會比較快?
然後再提出兩者不同以及你不懂原理的地方?
我有先完全照著你做,都沒有出任何錯誤,才套用自己的模板,後來有發現錯誤是@Styles.Render(“~/Content/css”)
@Scripts.Render(“~/bundles/modernizr”)
加了的話,登入註冊按鈕不見,不加的話其他頁面就會格式亂掉,還是說加賴好友,我傳截圖或是檔案給你看。主要是想請教在套用你的格式的情況下,讓按鈕能正常顯現
那你加我的 line 好友,我看一下你的問題
https://line.me/R/ti/p/%40lqk4190v
自己遇到的小問題想分享一下,在建立TABLE時,可以將個欄位的上限調高一些,自己在成功執行後輸入資料按下註冊時,發生
” System.Data.SqlClient.SqlException: ‘字串或二進位資料會被截斷。”
這樣的錯誤,原因在於某一格所輸入的資料長度超出當初欄位所設計的長度,所以才會出現這樣的錯誤,建議版主可以將建立TABLE那部分的SQL中可以將個欄位長度改長一點。
好的,謝謝建議
老師您好 我想請問您在打入System.Web.Configuration.WebConfigurationManager.ConnectionStrings
這段的時候就會出現 “名稱為 ‘System.Web.Configuration.WebConfigurationManager.ConnectionStrings’ 的 程序 中含有大於前置詞最大數目的前置詞。最大值為 3。”
請問該如何解決的 麻煩您了
請問你看到的是訊息是提示或是錯誤呢?
如果是提示的話,有可能是提醒你前面的 Namespace 是可以省略的,這個不影響編譯
是訊息錯誤 出現的”程序中含有大於前置詞最大數目的前置詞。最大值為 3。”而不是提示
所以就沒有辦法執行 該怎麼辦呢
她顯示的是錯誤訊息 所以不給我執行
只顯示”的 程序中含有大於前置詞最大數目的前置詞。最大值為 3。” 請問該怎麼辦呢
你能否加入我的 Line 好友呢,然後貼圖給我看呢
這樣我比較清楚你的錯誤內容
把您的錯誤「程序中含有大於前置詞最大數目的前置詞。最大值為 3」拿去 Google一下,就知道這不是程式的錯,是SQL Server的錯….可能要找一下您的資料庫、資料表