小編應各位的要求,馬不停蹄,快馬加鞭的終於:七天學會 Asp.Net MVC 第四篇出爐,在第四天的學習中,咱們主要了學習如何在MVC中如何實現認證受權等問題,本節主要講了驗證錯誤時的錯誤值,客戶端驗證,受權認證及登陸註銷功能的實現。html
七天學會ASP.NET MVC (一)——深刻理解ASP.NET MVCjquery
七天學會ASP.NET MVC (二)——ASP.NET MVC 數據傳遞瀏覽器
七天學會ASP.NET MVC (三)——ASP.Net MVC 數據處理安全
七天學會ASP.NET MVC (四)——用戶受權認證問題服務器
七天學會ASP.NET MVC (五)——Layout頁面使用和用戶角色管理cookie
實驗15 ——有關錯誤驗證的保留值。mvc
實驗16——添加客戶端驗證less
實驗17——添加受權認證函數
實驗18——在View中顯示用戶名工具
實驗19——實現註銷操做
實驗20——實現登陸頁面驗證
實驗21——實現登陸頁面客戶端驗證
總結
在上一節的實驗13,咱們介紹了服務器端的身份驗證,實驗14中添加了客戶端驗證的支持,但願每位讀者都可以把實驗14理解透徹,逐行代碼查看,保證每行代碼都理解了,這樣纔有助於理解咱們接下來的實驗。
實驗15中將學習如何在驗證失敗時,填充值。
1. 建立 CreateEmployeeViewModel 類。
在ViewModel文件夾下,新建類:
public class CreateEmployeeViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Salary { get; set; }
}
2. 修改 SaveEmployee 方法
爲了從新生成,重用Model Binder建立的 Employee 對象,修改 SaveEmployee 方法。
1: public ActionResult SaveEmployee(Employee e, string BtnSubmit)
2: {
3: switch (BtnSubmit)
4: {
5: case "Save Employee":
6: if (ModelState.IsValid)
7: {
8: EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();
9: empBal.SaveEmployee(e);
10: return RedirectToAction("Index");
11: }
12: else
13: {
14: CreateEmployeeViewModel vm = new CreateEmployeeViewModel();
15: vm.FirstName = e.FirstName;
16: vm.LastName = e.LastName;
17: if (e.Salary.HasValue)
18: {
19: vm.Salary = e.Salary.ToString();
20: }
21: else
22: {
23: vm.Salary = ModelState["Salary"].Value.AttemptedValue;
24: }
25: return View("CreateEmployee", vm); // Day 4 Change - Passing e here
26: }
27: case "Cancel":
28: return RedirectToAction("Index");
29: }
30: return new EmptyResult();
31: }
3. 填充View的值
3.1 將View設置爲強類型的View
在 CreateEmployee View文件開始添加如下代碼:
1: @using WebApplication1.ViewModels
2: @model CreateEmployeeViewModel
3.2 在響應控件中顯示Model值
1: ...
2:
3: ...
4:
5: ...
6:
7: <input type="text" id="TxtFName" name="FirstName" value="@Model.FirstName" />
8:
9: ...
10:
11: ...
12:
13: ...
14:
15: <input type="text" id="TxtLName" name="LastName" value="@Model.LastName" />
16:
17: ...
18:
19: ...
20:
21: ...
22:
23: <input type="text" id="TxtSalary" name="Salary" value="@Model.Salary" />
24:
25: ...
26:
27: ...
28:
29: ...
4. 運行點擊Add New連接
瀏覽器提示錯誤。咱們在實驗講述完以後,再來解釋爲何會出現錯誤。
5. 修改AddNew方法
1: public ActionResult AddNew()
2: {
3: return View("CreateEmployee」, new CreateEmployeeViewModel());
4: }
6. 運行測試
測試1
會出現驗證失敗,可是數字 56 仍然顯示在 Salary 文本框中。
測試2
如圖所示,姓名仍然保留在文本框中,卻未保留工資,接下來咱們來討論上述問題的解決辦法。
是不是真的將值保留?
不是,是從post數據中從新獲取的。
爲何須要在初始化請求時,在Add New 方法中傳遞 new CreateEmployeeViewModel()?
View中,試着將Model中的數據從新顯示在文本框中。
如:
<input id="TxtSalary" name="Salary" type="text" value="@Model.Salary" />
如上所示,能夠訪問當前Model的「First Name」屬性,若是Model 爲空,會拋出類沒法實例化的異常「Object reference not set to an instance of the class」。
當點擊」Add New「超連接時,請求會經過Add New方法處理,在該Action 方法中,能夠不傳遞任何數據。即就是,View中的Model屬性爲空。所以會拋出「Object reference not set to an instance of the class」異常。爲了解決此問題,因此會在初始化請求時,傳」new CreateEmployeeViewModel()「。
上述的這些功能,有什麼方法能夠自動生成?
使用HTML 幫助類就能夠實現。在實驗16中咱們會講解HTML 幫助類。
首先了解,須要驗證什麼?
1. FirstName 不能爲空
2. LastName字符長度不能大於5
3. Salary不能爲空,且應該爲數字類型
4. FirstName 不能包含@字符
接下來,實現客戶端驗證功能
1. 建立JavaScript 驗證文件
在Script文件下,新建JavaScript文件,命名爲「Validations.js」
2. 建立驗證函數
在「Validations.js」文件中建立驗證函數:
1: function IsFirstNameEmpty() {
2: if (document.getElementById('TxtFName').value == "") {
3: return 'First Name should not be empty';
4: }
5: else { return ""; }
6: }
7:
8: function IsFirstNameInValid() {
9: if (document.getElementById('TxtFName').value.indexOf("@") != -1) {
10: return 'First Name should not contain @';
11: }
12: else { return ""; }
13: }
14: function IsLastNameInValid() {
15: if (document.getElementById('TxtLName').value.length>=5) {
16: return 'Last Name should not contain more than 5 character';
17: }
18: else { return ""; }
19: }
20: function IsSalaryEmpty() {
21: if (document.getElementById('TxtSalary').value=="") {
22: return 'Salary should not be empty';
23: }
24: else { return ""; }
25: }
26: function IsSalaryInValid() {
27: if (isNaN(document.getElementById('TxtSalary').value)) {
28: return 'Enter valid salary';
29: }
30: else { return ""; }
31: }
32: function IsValid() {
33:
34: var FirstNameEmptyMessage = IsFirstNameEmpty();
35: var FirstNameInValidMessage = IsFirstNameInValid();
36: var LastNameInValidMessage = IsLastNameInValid();
37: var SalaryEmptyMessage = IsSalaryEmpty();
38: var SalaryInvalidMessage = IsSalaryInValid();
39:
40: var FinalErrorMessage = "Errors:";
41: if (FirstNameEmptyMessage != "")
42: FinalErrorMessage += "\n" + FirstNameEmptyMessage;
43: if (FirstNameInValidMessage != "")
44: FinalErrorMessage += "\n" + FirstNameInValidMessage;
45: if (LastNameInValidMessage != "")
46: FinalErrorMessage += "\n" + LastNameInValidMessage;
47: if (SalaryEmptyMessage != "")
48: FinalErrorMessage += "\n" + SalaryEmptyMessage;
49: if (SalaryInvalidMessage != "")
50: FinalErrorMessage += "\n" + SalaryInvalidMessage;
51:
52: if (FinalErrorMessage != "Errors:") {
53: alert(FinalErrorMessage);
54: return false;
55: }
56: else {
57: return true;
58: }
59: }
3. 在 「CreateEmployee」View 中添加 Validations.js文件引用:
1: <script src="~/Scripts/Validations.js"></script>
4. 在點擊 SaveEmployee按鈕時,調用驗證函數,以下:
<input type="submit" name="BtnSubmit" value="Save Employee" onclick="IsValid();"/>
5. 運行測試
點擊 Add New 連接,跳轉到 」Add New「頁面
測試1
測試2
爲何在點擊」SaveEmployee 「按鈕時,須要返回關鍵字?
如以前實驗9討論的,當點擊提交按鈕時,是給服務器發送請求,驗證失敗時對服務器請求沒有意義。經過添加」return false「代碼,能夠取消默認的服務器請求。
在 IsValid函數將返回false,表示驗證失敗來實現預期的功能。
除了提示用戶,是否能夠在當前頁面顯示錯誤信息?
是能夠得,只須要爲每一個錯誤建立span 標籤,默認設置爲不可見,當提交按鈕點擊時,若是驗證失敗,使用JavaScript修改錯誤的可見性。
自動獲取客戶端驗證還有什麼方法?
是,當使用Html 幫助類,可根據服務端驗證來獲取自動客戶端驗證,在之後會詳細討論。
服務器端驗證還有沒有必須使用?
在一些JavaScript腳本代碼沒法使用時,服務器端能夠替代使用。
在實驗17中,會改進GetView方法,使其變得更加安全,只有合法的用戶纔可以訪問該方法。
在本系列的第一講中,咱們瞭解了Asp.Net和MVC的意義,知道MVC是Asp.net的一部分,MVC繼承了ASP.NET的全部特徵,包含表單認證。
先來了解ASP.NET是如何進行Form認證的。
1. 建立 AuthenticationController 和 Login 行爲方法
右擊controller文件夾,選擇添加新Controller,新建並命名爲」Authentication「即Controller的全稱爲」AuthenticationController「。
新建Login action方法:
1: public class AuthenticationController : Controller
2: {
3: // GET: Authentication
4: public ActionResult Login()
5: {
6: return View();
7: }
8: }
2. 建立Model
在Model 文件夾下新建Model,命名爲 UserDetails。
1: namespace WebApplication1.Models
2: {
3: public class UserDetails
4: {
5: public string UserName { get; set; }
6: public string Password { get; set; }
7: }
8: }
3. 建立Login View
在「~/Views/Authentication」文件夾下,新建View命名爲Login,並將UserDetails轉換爲強View類型。
在View中添加如下代碼:
1: @model WebApplication1.Models.UserDetails
2:
3: @{
4:
5: Layout = null;
6:
7: }
8:
9: <!DOCTYPE html>
10:
11: <html>
12:
13: <head>
14:
15: <meta name="viewport" content="width=device-width" />
16:
17: <title>Login</title>
18:
19: </head>
20:
21: <body>
22:
23: <div>
24:
25: @using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))
26:
27: {
28:
29: @Html.LabelFor(c=>c.UserName)
30:
31: @Html.TextBoxFor(x=>x.UserName)
32:
33:
34:
35: <br />
36:
37: @Html.LabelFor(c => c.Password)
38:
39: @Html.PasswordFor(x => x.Password)
40:
41: <br />
42:
43:
44: <input type="submit" name="BtnSubmit" value="Login" />
45:
46: }
47:
48: </div>
49:
50: </body>
51:
52: </html>
在上述代碼中能夠看出,使用HtmlHelper類在View中替代了純HTML代碼。
示例1:
1: @Html.TextBoxFor(x=>x.UserName)
轉換爲HTML代碼
<input id="UserName" name="UserName" type="text" value="" />
示例2:
1: @using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))
2: {
3: }
轉換爲HTML代碼:
1: <form action="/Authentication/DoLogin" method="post">
2: </form>
4. 運行測試
輸入Login action方法的URL:「http://localhost:8870/Authentication/Login」
5. 實現Form認證
打開 Web.config文件,在System.Web部分,找到Authentication的子標籤。若是不存在此標籤,就在文件中添加Authentication標籤。
設置Authentication的Mode爲Forms,loginurl設置爲」Login」方法的URL.
1: <authentication mode="Forms">
2: <forms loginurl="~/Authentication/Login"></forms>
3: </authentication>
6. 讓Action 方法更安全
在Index action 方法中添加認證屬性 [Authorize].
1: [Authorize]
2: public ActionResult Index()
3: {
4: EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel();
5: ......
7. 運行測試,輸入 EmployeeController 的 Index action的URL:「http://localhost:8870/Employee/Index」
對於Index action的請求會自動重連接到 login action。
8. 建立業務層功能
打開 EmployeeBusinessLayer 類,新建 IsValidUser方法:
1: public bool IsValidUser(UserDetails u)
2: {
3: if (u.UserName == "Admin" && u.Password == "Admin")
4: {
5: return true;
6: }
7: else
8: {
9: return false;
10: }
11: }
9. 建立 DoLogin action 方法
打開 AuthenticationController 類,新建action 方法命名爲 DoLogin。
當點擊登陸時,Dologin action 方法會被調用。
Dologin 方法的功能:
1: [HttpPost]
2: public ActionResult DoLogin(UserDetails u)
3: {
4: EmployeeBusinessLayer bal = new EmployeeBusinessLayer();
5: if (bal.IsValidUser(u))
6: {
7: FormsAuthentication.SetAuthCookie(u.UserName, false);
8: return RedirectToAction("Index", "Employee");
9: }
10: else
11: {
12: ModelState.AddModelError("CredentialError", "Invalid Username or Password");
13: return View("Login");
14: }
15: }
10.在View 中顯示信息
打開Login View,在 @Html.BeginForm中 添加如下代碼
1: @Html.ValidationMessage("CredentialError", new {style="color:red;" })
2: @using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))
3: {
11. 運行測試
測試1
測試2
爲何Dologin會添加 HttpPost 屬性,還有其餘相似的屬性嗎?
該屬性可以使得DoLogin 方法打開Post 請求。若是有人嘗試獲取DoLogin,將不會起做用。還有不少相似的屬性如HttpGet,HttpPut和HttpDelete屬性.
FormsAuthentication.SetAuthCookie是必須寫的嗎?
是必須寫的。讓咱們瞭解一些小的工做細節。
FormsAuthentication.SetAuthCookie將添加 「Authentication」特殊的Cookie來響應。
是否意味着沒有Cookies,FormsAuthentication 將不會有做用?
不是的,可使用URI代替Cookie。
打開Web.Config文件,修改Authentication/Forms部分:
1: <forms cookieless="UseUri" loginurl="~/Authentication/Login"></forms>
受權的Cookie會使用URL傳遞。
一般狀況下,Cookieless屬性會被設置爲「AutoDetect「,表示認證工做是經過Cookie完成的,是不支持URL傳遞的。
FormsAuthentication.SetAuthCookie中第二個參數」false「表示什麼?
false決定了是否建立永久有用的Cookie。臨時Cookie會在瀏覽器關閉時自動刪除,永久Cookie不會被刪除。可經過瀏覽器設置或是編寫代碼手動刪除。
當憑證錯誤時,UserName 文本框的值是如何被重置的?
HTML 幫助類會從Post 數據中獲取相關值並重置文本框的值。這是使用HTML 幫助類的一大優點。
Authorize屬性有什麼用?
Asp.net MVC中提供四種過濾器來過濾請求和響應的,Authorize屬性是在Authorize過濾器以後執行的,能夠確保受權請求Action 方法處理。
須要爲每一個Action 方法添加受權屬性嗎?
不須要,能夠將受權屬性添加到Controller 層或 Global 層。
在本實驗中,咱們會在View中顯示已登陸的用戶名
1. 在ViewModel 中添加 UserName
打開 EmployeeListViewModel,添加屬性叫:UserName。
1: public class EmployeeListViewModel
2: {
3: public List<EmployeeViewModel><employeeviewmodel> Employees { get; set; }
4: public string UserName { get; set; }
5: }
6: </employeeviewmodel>
2. 給 ViewModel UserName 設置值
修改 EmployeeController,修改 Index 方法。
1: public ActionResult Index()
2: {
3: EmployeeListViewModel employeeListViewModel = new EmployeeListViewModel();
4: employeeListViewModel.UserName = User.Identity.Name; //New Line
5: ......
3. 顯示 View UserName
1: <body>
2:
3: <div style="text-align:right"> Hello, @Model.UserName </div>
4:
5: <hr />
6:
7: <a href="/Employee/AddNew">Add New</a>
8:
9: <div>
10:
11: <table border="1"><span style="font-size: 9pt;">
12: </span>
4. 運行
1. 建立註銷連接,打開Index.cshtml 建立 Logout 連接以下:
1: <body>
2:
3: <div style="text-align:right">Hello, @Model.UserName
4:
5: <a href="/Authentication/Logout">Logout</a></div>
6:
7: <hr />
8:
9: <a href="/Employee/AddNew">Add New</a>
10:
11: <div>
12:
13: <table border="1">
2. 建立Logout Action 方法
打開 AuthenticationController 添加新的Logout action方法:
1: public ActionResult Logout()
2: {
3: FormsAuthentication.SignOut();
4: return RedirectToAction("Login");
5: }
3. 運行
1. 添加 data annotation
打開 UserDetails.cs,添加 Data Annotation:
1: public class UserDetails
2: {
3:
4: [StringLength(7,MinimumLength=2, ErrorMessage = "UserName length should be between 2 and 7")]
5: public string UserName { get; set; }
6: public string Password { get; set; }
7: }
2. 在View 中顯示錯誤信息
修改 Login.cshtml可以提示錯誤信息。
1: @using (Html.BeginForm("DoLogin", "Authentication", FormMethod.Post))
2: {
3: @Html.LabelFor(c=>c.UserName)
4: @Html.TextBoxFor(x=>x.UserName)
5: @Html.ValidationMessageFor(x=>x.UserName)
6: ......
3. 修改 DoLogin
修改 DoLogin action 方法:
1: [HttpPost]
2: public ActionResult DoLogin(UserDetails u)
3: {
4: if (ModelState.IsValid)
5: {
6: EmployeeBusinessLayer bal = new EmployeeBusinessLayer();
7: if (bal.IsValidUser(u))
8: {
9: FormsAuthentication.SetAuthCookie(u.UserName, false);
10: return RedirectToAction("Index", "Employee");
11: }
12: else
13: {
14: ModelState.AddModelError("CredentialError", "Invalid Username or Password");
15: return View("Login");
16: }
17: }
18: else
19: {
20: return View("Login");
21: }
22: }
4. 運行
在本實驗中介紹一種方法實現客戶端驗證
1. 下載 jQuery unobtrusive Validation文件
右擊項目,選擇「Manage Nuget packages」,點擊在線查找」jQuery Unobtrusive「,安裝」Microsoft jQuery Unobtrusive Valiadtion「
2. 在View 中添加 jQuery Validation 引用
在Scripts文件中,添加如下 JavaScript文件
打開 Login.cshtml,在文件頂部包含這三個js文件:
1: <script src="~/Scripts/jquery-1.8.0.js"></script>
2: <script src="~/Scripts/jquery.validate.js"></script>
3: <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
3. 運行
客戶端驗證是如何實現的?
如上所述,客戶端驗證並非很麻煩,在Login View中,HTML元素可以使用幫助類來生成,Helper 函數可以根據Data Annotation屬性的使用生成帶有屬性的HTML 標記元素。
例如:
1: @Html.TextBoxFor(x=>x.UserName)
2: @Html.ValidationMessageFor(x=>x.UserName)
根據以上代碼生成的HTML 代碼以下:
1: <input data-val="true" data-val-length="UserName length should be between 2 and 7" data-val-length-max="7" data-val-length-min="2" id="UserName" name="UserName" type="text" value="" />
2: <span class="field-validation-error" data-valmsg-for="UserName" data-valmsg-replace="true"> </span>
jQuery Unobtrusive驗證文件會使用這些自定義的HTML 屬性,驗證會在客戶端自動生成。自動進行客戶端驗證是使用HTML 幫助類的又一大好處。
是否可使用不帶HTML 幫助類的JavaScript 驗證?
是,可手動添加屬性。
有了本節MVC關於用戶受權與客戶端驗證的講解,相信會對你們的MVC開發過程有所幫助。在使用MVC進行開發時,還能夠利用一些開發工具。使用 ComponentOne Studio ASP.NET MVC 這款輕量級控件,在開發效率大大提升的同時,工做量也會大大減小。
這就是本節所講的用戶受權與客戶端驗證的實現,在第五天咱們會講到更高級的應用,請持續關注,不要走開哦!
原文連接 http://www.codeproject.com/Articles/996832/Learn-MVC-Project-in-Days-Day