日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

7 天玩转 ASP.NET MVC — 第 3 天

發布時間:2025/3/20 asp.net 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 7 天玩转 ASP.NET MVC — 第 3 天 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • 第 1 天
  • 第 2 天
  • 第 3 天
  • 第 4 天
  • 第 5 天
  • 第 6 天
  • 第 7 天

0. 前言

我們假定你在開始學習時已經閱讀了前兩天的學習內容。在第 2 天我們完成了關于顯示 Employees 列表的項目。

在第三天,我們將會通過介紹數據訪問層和數據入口將它升級到一個新的層次。

1. 數據訪問層

在真實場景的項目中,如果沒有 Database,那么這個項目是未完成的。在我們的項目中,我們還沒有談到數據庫。第三天的首個 Lab 將會學習數據庫和數據庫層。

這里我們將使用 SQL Server 和 Entity Framework 來創建 Database 和 Database 訪問層。

簡單來說,什么是 Entity Framework?

這是一個 ORM 工具。ORM 代表的是 Object Relational Mapping。即:對象關系映射。

在 RDBMS 領域中,我們所談論的 Tables 表格和 Columns 列的這些方面,在 .NET 領域(面向對象領域)中被稱為 Classes 類,對象和屬性。

當我們思考任何有關數據驅動應用的方式時,都可以得出以下兩種方式:

  • 書寫代碼來和數據庫打交道(被稱為數據訪問層和數據庫邏輯)

  • 書寫代碼來將數據庫數據映射到面向對象中,反之亦然。

ORM 是一個工具,可以自動做如上兩件事。Entity Framework 是微軟的 ORM 工具。

什么是 Code First 方法?

在 Entity Framework 中,我們可以使用如下三種的任意方法:

  • Database First 方法。創建一個有表,列和關系的數據庫。Entity Framework 將會生成對應的 Model 類(業務實體)和數據訪問層代碼。

  • Model First 方法。在這個方法中,Model 類和它們之間的聯系將會被 Model 設計者在 Visual Studio 中被手動定義。然后 Entity Framework 會自動創建數據訪問層和擁有表、列以及關系的數據庫。

  • Code First 方法。在這個方法中,手動創建 POCO 類。這些類中的關系將會被代碼所定義。當應用第一次執行時,Entity Framework 將會自動在數據庫服務器上創建數據訪問層和擁有表、列以及關系的數據庫。

什么是 POCO 類?

POCO 代表的是「Plain Old CLR Objects」。POCO 類代表的是我們所創建的簡單 .NET 類。在我們之前的例子中, Employee 類是一個簡單的 POCO。

2. Lab 8 — 向項目中添加數據訪問層

第一步:創建數據庫

連接 SQL Server 然后創建一個新的數據庫,命名為「SalesERPDB」。

第二步:創建 ConnectionString

打開 Web.config 文件,然后在 Configuration 區域內添加如下片段:

<connectionStrings> <add connectionString="Data Source=(local);Initial Catalog=SalesERPDB;Integrated Security=True"name="SalesERPDAL" providerName="System.Data.SqlClient"/> </connectionStrings>

第三步:添加 Entity Framework 引用

右擊項目-> 管理 Nuget 包。搜索 Entity Framework,然后點擊安裝。

第四步:創建數據訪問層

  • 在根目錄下創建一個新文件夾,命名為「DataAccessLayer」,然后在里面創建一個新的類,命名為「SalesERPDAL」。

  • 在類頂部寫引用聲明如下
    using System.Data.Entity;

  • 繼承 DbContext 的類「SalesERPDAL」

    public class SalesERPDAL: DbContext
    {
    }

第五步:為 Employee 類創建主鍵

打開 Employee 類并在類頂部聲明如下:

using System.ComponentModel.DataAnnotations;

在 Employee 類中添加 EmployeeId 屬性,然后將其標注為 Key 屬性。

public class Employee {[Key]public int EmployeeId { get; set; }public string FirstName { get; set; }public string LastName { get; set; }public int Salary { get; set; } }

第六步:定義映射

在「SalesERPDAL」類中添加如下聲明語句:

using WebApplication1.Models;

在 SalesERPDAL 類中重寫 OnModelCreating 方法。

protected override void OnModelCreating(DbModelBuilder modelBuilder) {modelBuilder.Entity<employee>().ToTable("TblEmployee");base.OnModelCreating(modelBuilder); }

注意:上述代碼中的片段「TblEmployee」代表的是表名。在運行時講自動被創建。

第七步:在數據庫中創建 Employees 屬性

在「SalesERPDAL」類中創建一個新屬性,命名為 Employee,如下所示:

public DbSet<employee> Employees{get;set;}

DbSet 將會展示所有可以在數據庫中查詢到的 Employees。

第八步:改變業務層代碼,從數據庫中讀取數據

打開 EmployeeBusinessLayer 類,在頂部加上聲明如下:

using WebApplication1.DataAccessLayer;

現在改變 GetEmployees 方法如下:

public List<employee> GetEmployees() {SalesERPDAL salesDal = new SalesERPDAL();return salesDal.Employees.ToList(); }

第九步:執行并測試

按下 F5,并執行應用。

現在的數據庫中,我們沒有任何的 Employees,所以我們看見的是一個空白的 Grid。

查看數據庫,現在我們可以在 TblEmployee 表中看到所有的列。

第十步:插入測試數據

向 TblEmployee 表中插入一些測試數據。

第十一步:執行并測試應用

按下 F5 并再次運行應用。

Lab 8 的 Q&A

什么是 DbSet?

DbSet 簡單地表示了可以從數據庫中查詢到的實體集合。當我們再次寫一個 Linq 查詢時,DbSet 對象會對查詢進行內存轉換,然后觸發數據庫。

在我們的例子中,「Employee」是一個 DbSet,它承載了所有可以從數據庫中查詢到的 Employee 實體對象。每一次我們嘗試訪問「Employees」時,它都將從“TblEmployee”表中獲取記錄,然后將其轉換為「Employees」對象并返回集合。

數據庫連接串和數據訪問層是如何連接的?

Mapping 通過名稱來實現。在我們的例子中,ConnectionString 名稱和數據訪問層類的名稱是一樣的,即「SalesERPDAL」,因此它們是自動映射的。

我們可以更改 ConnectionString 的名稱嗎?

答案是肯定的。在這個例子中,我們需要在數據訪問層類中定義一個構造函數如下:

public SalesERPDAL():base("NewName") { }

3. 組織所有

我們需要做幾個改變,使得所有是有組織和有意義的。

第一步:重命名

  • 「TestController」換名為 「EmployeeController」。

  • GetView 行為方法改為 Index。

  • Test 文件夾(Views 文件夾下) 改為 Employee

  • 「MyView」視圖改為「Index」。

第二步:從 EmployeeListViewModel 中刪除 UserName 屬性

第三步:從視圖中刪除 UserName

打開 View/Employee.Index.cshtml 視圖,然后從中刪除 UserName。

簡單來說,就是刪除如下代碼:

Hello @Model.UserName <hr />

第四步:在 EmployeeController 中更改 Index 行為方法

更改 EmployeeController 中的 Index 行為方法如下:

public ActionResult Index() {&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;employeeListViewModel.Employees = empViewModels;//employeeListViewModel.UserName = "Admin";-->Remove this line -->Change1return View("Index", employeeListViewModel);//-->Change View Name -->Change 2 }

現在執行的 URL 將會為:「…/Employee/Index」。

4. Lab 9 — 創建 Data Entry Screen

第一步:創建 Action 方法

在 EmployeeController 中創建一個 Action 方法,命名為「AddNew」,如下:

public ActionResult AddNew() {return View("CreateEmployee"); }

第二步:創建 View

在文件夾 View/Employee 下創建一個 View,命名為「CreateEmployee」。代碼如下:

@{Layout = null; } <!DOCTYPE html> <html><head><meta name="viewport" content="width=device-width" /><title>CreateEmployee</title></head><body><div><form action="/Employee/SaveEmployee" method="post">First Name: <input type="text" id="TxtFName" name="FirstName" value="" /><br />Last Name: <input type="text" id="TxtLName" name="LastName" value="" /><br />Salary: <input type="text" id="TxtSalary" name="Salary" value="" /><br /><input type="submit" name="BtnSave" value="Save Employee" /><input type="button" name="BtnReset" value="Reset" /></form></div></body> </html>

第三步:在 Index 視圖中創建一個鏈接

打開 Index.cshtml,然后增加一個超鏈接指向 AddNew 行為的URL。

<ahref="/Employee/AddNew">Add New</a>

第四步:執行并測試應用

按下 F5 并執行應用。

Lab 9 的 Q&A

Form 標簽的目的是什么?

在第一天的系列學習中,我們已經明白了「Web 世界不會遵循事件驅動編程模型。它遵循的是請求響應模型。終端用戶發出請求,然后服務器給出響應。」Form 標簽是 HTML 中做出響應的其中一種方式。只要標簽里的提交按鈕被點擊,一個請求就將發送給動作屬性中指定的 URL 中。

Form 標簽中的方法屬性是什么?

它決定了請求的類型。請求也許是如下的其中一種:get、post、put 或者是 delete。

  • Get:當我們想獲取什么數據時

  • Post:當我們想創建什么數據時

  • Put:當我們想更新什么數據時

  • Delete:當我們想刪除什么數據時

運用 Form 標簽和通過瀏覽器地址欄或者超鏈接來發出請求,有何區別?

當我們使用 Form 標簽來發送請求時,所有輸入控件中的值都會伴隨著請求一起被處理。

Checkbox、Radio 按鈕和 Dropdowns 控件中的值也會被發送嗎?

答案是肯定的。所有輸入控件(輸入類型為 Text,Radio,Checkbox)以及 Dropdowns(表示的是被選中的元素)都會被發送。

輸入的值如何發送給服務器?

當請求的類型是 Get、Put 或者 Delete 時,輸入的值會以查詢字符串參數的方式發送。

當請求的類型是 Post 時,輸入的值會以 Post 數據發送。

輸入控件中的 Name 屬性的目的是什么?

就像我們之前所談論的,當按鈕被點擊時,輸入控件中的值將會隨著請求一起被發送。這會使得服務器在這個時刻接收到多于一個的值。為了在發送值的時候,單獨區別每一個值,就會為它們附加上一個 Key,這個 Key 就是「Name」屬性。

Name 和 Id 屬性的目的是否是相同的?

答案是否定的。就像剛才的問題所說,當請求發生時,「Name」屬性被 HTML 所使用,而「Id」屬性被開發者所使用,為一些 JavaScript 實現一些動態功能。

「input type = submit」 和 「input type = button」有什么區別?

當我向服務器發送請求時,Submit 按鈕會被特殊用到。而一個簡單的按鈕是用來處理一些客戶端的行為的。簡單的按鈕不會自己做一些事情。

5. Lab 10 — 在服務器/Controller 獲取 Posted 數據

第一步:創建 SaveEmployee 行為方法

在 Employee 控制器中創建一個行為方法,命名為 SaveEmployee,代碼如下:

public string SaveEmployee(Employee e) {return e.FirstName + "|"+ e.LastName+"|"+e.Salary; }

第二步:執行并測試

按下 F5 并執行應用。

Lab 10 的 Q&A

在 Action 方法里,Textbox 的值是如何更新 Employee 對象的?

在 ASP.NET MVC 中,存有一個概念,叫做 Model Binder。

  • 無論何時一個包含參數的請求向 Action 方法發送時,Model Binder 都會自動執行。

  • Model Binder 將會遍歷方法的所有原始參數,然后將它們與發送過來的數據的參數的名稱相對比。(發送過來的數據意味著要么是 Posted 數據,或者是查詢字符串)。當匹配成功時,會依照發送過來的數據分配給參數。

  • 當 Model Binder 遍歷完每一個類參數中的每一個屬性后,然后和發送過來的數據做對比。當匹配成功后,依照發送過來的數據分配給參數。

當兩個參數是特指的,將會發生什么?例如第一個是「Employee」,第二個是「FirstName」?

FirstName 將會在初始的變量 FirstName 中更新,也會在 e.FirstName 屬性中更新。

ModelBinder 可以和組合關系一起運用嗎?

答案是肯定的。但是在這個情形下控件的名稱應該被給出。例如:

Customer 和 Address 類的代碼如下:

public class Customer {public string FName{get;set;}public Address address{get;set;} } public class Address {public string CityName{get;set;}public string StateName{get;set;} }

在這種情形下,HTML 如下:

... ... ... <input type="text" name="FName"> <input type="text" name="address.CityName"> <input type="text" name="address.StateName"> ... ... ...

6. Lab 11 — 重置和取消按鈕

第一步:開始重置和取消按鈕

增加一個重置和取消按鈕,代碼如下:

... ... ... <input type="submit" name="BtnSubmit&rdquo; value="Save Employee" /><input type="button" name="BtnReset" value="Reset" onclick="ResetForm();" /><input type="submit" name="BtnSubmit" value="Cancel" />

注意:保存和取消按鈕都有相同的「Name」屬性,即「BtnSubmit」。

第二步:定義 ResetForm 方法

在 HTML 頂部區域增加一個 Script 標簽,用于創建一個 JavaScript 方法,命名為 ResetForm。代碼如下:

<script>function ResetForm() {document.getElementById('TxtFName').value = "";document.getElementById('TxtLName').value = "";document.getElementById('TxtSalary').value = "";} </script>

第三步:在 EmployeeController 的 SaveEmployee 行為方法中實現取消點擊事件。

改變 SaveEmployee 行為方法如下:

public ActionResult SaveEmployee(Employee e, string BtnSubmit) {switch (BtnSubmit){case "Save Employee":return Content(e.FirstName + "|" + e.LastName + "|" + e.Salary);case "Cancel":return RedirectToAction("Index");}return new EmptyResult(); }

第四步:執行應用

按下 F5 并執行應用。通過點擊“Add New”鏈接導航到 AddNew 屏幕。

第五步:測試重置功能

第六步:測試 Save 和 Cancel 功能

Lab 11 的 Q&A

為什么保存和取消按鈕的名稱是一樣的?

我們知道,一旦提交按鈕被點擊,一個請求就會被發送到服務器端。并且伴隨著請求,所有輸入控件的值也一起被發送。

Submit 按鈕也是一個輸入按鈕。因為按鈕的值也會被發送。

當保存按鈕被點擊時,保存按鈕的值,即「Save Employee」將會隨著請求一起被發送。當取消按鈕被點擊時,取消按鈕的值,即「Cancel」將會隨著請求一起被發送。

在 Action 方法中。Model Binder 將會處理這些工作。它將會依照輸入的值(伴隨著請求)更新參數的值。

實現多個提交按鈕的方式是什么?

這里有多個方式。我介紹其中三種。

  • 隱藏 Form 元素

第一步:在視圖中創建一個隱藏 Form 元素

<form action="/Employee/CancelSave" id="CancelForm" method="get" style="display:none"> </form>

第二步:改變 Submit 按鈕為一個常規按鈕,并且通過 JavaScript 將上面的 Form 發送

<input type="button" name="BtnSubmit" value="Cancel" onclick="document.getElementById('CancelForm').submit()" />
  • 運用 JavaScript 動態地改變動作 URL

    ... ... <input type="submit" name="BtnSubmit" value="Save Employee" οnclick="document.getElementById('EmployeeForm').action = '/Employee/SaveEmployee'" /> ... <input type="submit" name="BtnSubmit" value="Cancel" οnclick="document.getElementById('EmployeeForm').action = '/Employee/CancelSave'" />
  • Ajax

不再運用 Submit 按鈕,取而代之的是簡單的輸入按鈕,然后運用 JQuery 或者其它庫來實現純 Ajxa 請求。

為什么我們在實現重置功能時,沒使用「input type = reset」?

「input type = reset」控件不會清除值,它只是將控件的值改為默認的值。例如:

<input type="text" name="FName" value="Sukesh">

在這個例子中,控件的默認值是「Sukesh」。

如果我們運用「input type = reset」來實現重置功能,那么每一次點擊重置按鈕,默認的值「Sukesh」將會被設置到 Textbox 中。

當名稱沒有與類中的屬性名稱匹配時,會怎樣?

這是一個在面試中經常被問到的常規問題。

例如我們有一段 HTML 代碼如下:

First Name: <input type="text" id="TxtFName" name="FName" value="" /><br /> Last Name: <input type="text" id="TxtLName" name="LName" value="" /><br /> Salary: <input type="text" id="TxtSalary" name="Salary" value="" /><br />

現在我們的 Model 類包含的屬性名稱有 FirstName,LastName 和 Salary。因此默認的 Model Binder 將不會在這里處理。

在這種情形下,我們有三種解決方案:

  • 在 Action 方法內部,運用 Request.Form 語法來檢索發送過來的值,然后手動構造 Model 對象如下:

    public ActionResult SaveEmployee()
    {
    Employee e = new Employee();
    e.FirstName = Request.Form["FName"];
    e.LastName = Request.Form["LName"];
    e.Salary = int.Parse(Request.Form["Salary"])
    ...
    ...
    }

  • 運用參數名稱,然后手動創建 Model 對象如下:

    public ActionResult SaveEmployee(string FName, string LName, int Salary)
    {
    Employee e = new Employee();
    e.FirstName = FName;
    e.LastName = LName;
    e.Salary = Salary;
    ...
    ...
    }

  • 創建自定義的 Model Binder 來替換默認的 Model Binder。

第一步:創建自定義的 Model Binder

public class MyEmployeeModelBinder : DefaultModelBinder {protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType){Employee e = new Employee();e.FirstName = controllerContext.RequestContext.HttpContext.Request.Form["FName"];e.LastName = controllerContext.RequestContext.HttpContext.Request.Form["LName"];e.Salary = int.Parse(controllerContext.RequestContext.HttpContext.Request.Form["Salary"]);return e;} }

第二步:用這個新的 Model Binder 來替換默認的 Model Binder

public ActionResult SaveEmployee([ModelBinder(typeof(MyEmployeeModelBinder))]Employee e, string BtnSubmit) {...... }

RedirectToFunction 函數是做什么的?

它用來產生 RedirectToRouteResult,就像 ViewResult 和 ContentResult一樣(在第一天學習中探討)。RedirectToRouteResult 是 ActionResult 的子類,它代表的是間接的響應。當瀏覽器接到 RedirectToRouteResult,它就會產生新的請求到一個新的行為方法。

注:這里瀏覽器對新的請求是有責任的,因此 URL 將會更新到一個新的 URL。

什么是 EmptyResult?

它是 ActionResult 的其中一個子類。當瀏覽器接到的響應是 EmptyResult 時,它將會簡單地呈現一個空白屏幕。它簡單地代表「No Result」。

在我們的例子中,這種情形不會發生。只要確保所有的代碼路徑返回的值。

注:當 Action 方法返回的值是空的,結果等同于 EmptyResult。

7. Lab 12 — 在數據庫中保存記錄并更新 Grid

第一步:在 EmployeeBusinessLayer 中創建 SaveEmployee

public Employee SaveEmployee(Employee e) {SalesERPDAL salesDal = new SalesERPDAL();salesDal.Employees.Add(e);salesDal.SaveChanges();return e; }

第二步:改變 SaveEmployee 行為方法

在 EmployeeController 中,改變 SaveEmployee 行為方法,代碼如下:

public ActionResult SaveEmployee(Employee e, string BtnSubmit) {switch (BtnSubmit){case "Save Employee":EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();empBal.SaveEmployee(e);return RedirectToAction("Index");case "Cancel":return RedirectToAction("Index");}return new EmptyResult(); }

第三步:執行并測試

按下 F5 并執行應用。導航到 Data 入口屏幕并輸入一些合法的值。

8. Lab 13 — 增加服務器端認證

在 Lab 10 中,我們已經了解了 Model Binder 的基本功能。現在我們來更多地了解下。

  • Model Binder 通過發送過來的數據來更新 Employee 對象。

  • 但是這個不是 Model Binder 的唯一功能。Model Binder 還更新 ModelState。

  • 它有一個屬性,稱為 IsValid,這個決定了 Model(即 Employee 對象)是否更新成功了。如果服務器端的認證失敗了,Model 將不會更新。

  • 它承載了認證錯誤。例如:ModelState["FirstName"].Errors 包含了與 First Name 相關的錯誤。

  • 它承載了發送過來的數據值。(Posted 數據或者是查詢字符串數據)

在 ASP.NET MVC 中,我們運用 DataAnnotations 來實現服務器端的認證。

在了解 Data Annotation 之前,我們先了解一些 Model Binder。

ModelBinder 如何處理初始數據類型?

當 Action 方法包含初始類型參數時,Model Binder 將會把參數的名稱與發送過來的數據進行對比。(發送過來的數據是 Posted 數據或者是查詢字符串)

  • 當匹配成功時,將會依照發送過來的數據分配給參數。

  • 當匹配失敗時,參數將會被分配給默認值。(對于整型的默認值是0,對于字符串的默認值是 null)

  • 當數據類型不匹配的異常被拋出時,這種情況下不會進行分配操作。

Model Binder 如何處理類?

當參數是一個類參數,Model Binder 將會遍歷所有類的所有屬性,并且將每一個屬性名稱與發送過來的數據做對比。

  • 當匹配成功時,如果發送過來的數據是空的。

Null 值將會被分配給屬性。如果不能分配,默認的值將會被設置,并且 ModelState.IsValid 將會被設置為 false。

當 Null 值可以分配給屬性時,這將會被視作不合法的值,因為屬性附上了認證,因此 ModelState.IsValid 將會被設置為 false。

  • 當匹配成功時,發送過來的數據不為空。

當數據類型不匹配時,將不會分配值。或者服務器端的認證失敗,將分配 Null 值。此時 ModelState.IsValid 將會被設置為 false。如果不能分配 Null 值,默認的值將會被設置。

  • 當匹配不成功時,參數將會被分配為默認值。(對于整型的默認值是0,對于字符串的默認值是 null)。在這種情形下,ModelState.IsValid 將不會受到影響。

現在讓我們了解一下如何向項目中增加認證功能。

第一步:運用 DataAnnotations 裝飾屬性。

在 Model 文件夾下打開 Employee 類,運用 DataAnnotation 來裝飾 FirstName 和 LastName,代碼如下:

public class Employee { ... ...[Required(ErrorMessage="Enter First Name")]public string FirstName { get; set; }[StringLength(5,ErrorMessage="Last Name length should not be greater than 5")]public string LastName { get; set; } ... ... }

第二步:改變 SaveEmployee 行為方法。

打開 EmployeeController,改變 SaveEmloyee 行為方法如下:

public ActionResult SaveEmployee(Employee e, string BtnSubmit) {switch (BtnSubmit){case "Save Employee":if (ModelState.IsValid){EmployeeBusinessLayer empBal = new EmployeeBusinessLayer();empBal.SaveEmployee(e);return RedirectToAction("Index");}else{return View("CreateEmployee ");}case "Cancel":return RedirectToAction("Index");}return new EmptyResult(); }

注:正如你所看見的,當 SaveEmployee 按鈕點擊后, ModelState.IsValid 失敗,ViewResult 指向「CreateEmloyee」視圖。

第三步:在視圖中呈現錯誤

改變「Views/Index/CreateEmployee.cshtml」中的代碼如下。

這次我們將會運用「Table」標簽來格式化一下 UI。

<table><tr><td>First Name:</td><td><input type="text" id="TxtFName" name="FirstName" value="" /></td></tr><tr><td colspan="2" align="right">@Html.ValidationMessage("FirstName")</td></tr><tr><td>Last Name:</td><td><input type="text" id="TxtLName" name="LastName" value="" /></td></tr><tr><td colspan="2" align="right">@Html.ValidationMessage("LastName")</td></tr><tr><td>Salary:</td><td><input type="text" id="TxtSalary" name="Salary" value="" /></td></tr><tr><td colspan="2" align="right">@Html.ValidationMessage("Salary")</td></tr><tr><td colspan="2"><input type="submit" name="BtnSubmit" value="Save Employee" /><input type="submit" name="BtnSubmit" value="Cancel" /><input type="button" name="BtnReset" value="Reset" onclick="ResetForm();" /></td></tr> </table>

第四步:執行并測試

按下 F5 并執行應用。導航到「Employee/AddNew」行為方法,并測試應用。

  • Test 1

  • Test 2

注:你也許會遇到如下錯誤。

「The model backing the 'SalesERPDAL' context has changed since the database was created. Consider using Code First Migrations to update the database.」

為了解決這個錯誤,僅僅在 Global.asax 文件中的 Application_Start 中添加如下聲明:

Database.SetInitializer(new DropCreateDatabaseIfModelChanges<SalesERPDAL>());

Database 類在命名空間 System.Data.Entity 中。

Lab 13 的 Q&A

@Html.ValidationMessage 是做什么事情的?

  • @ 意味著是 Razor 代碼。

  • Html 是 視圖中的 HtmlHelper 類的實例。

  • ValidationMessage 是 HtmlHelper 類的方法,用于呈現錯誤信息。

ValidationMessage 函數如何工作的?

ValidationMessage 是一個函數。它在運行時執行。就像我們之前所探討的,ModelBinder 更新 ModelState。ValidationMessage 根據 Key 值來從 ModelState 中獲取錯誤信息并呈現。

例如:ValidationMessage("FirstName") 呈現有關 First Name 的錯誤信息。

我們還有其它類似于 Required 和 StringLength 的屬性嗎?

答案是肯定的。如下所示:

  • DataType。確保數據是指定的類型,例如郵箱、信用卡號、URL 等。

  • EnumDataTypeAttribute。確保在 Enumeration 中存在該值。

  • Range Attribute。確保值在一個指定的區域內。

  • Regular。認證值是否是指定的表達式。

  • Required。確保值是存在的。

  • StringLength。認證字符串中的最大和最小字符長度。

Salary 是如何認證的?

我們并沒有向 Salary 屬性添加 Data Annotation,但是它依然得到了認證。原因是這樣的,在更新模型的時候,Model Binder 依然考慮到了屬性的數據類型。

在 Test 1 中,我們保持 Salary 為一個空字符串。在這種情形下,因為我們有 Model Binder,ModelState.IsValid 將會為失敗的并且 ModelState 將會承載與 Salary 相關的錯誤認證信息,這些信息將會通過 Html.ValidationMessage("Salary") 被顯示在 View 中。

在 Test 2 中,Salary 數據類型匹配失敗,因此認證也是失敗的。

這意味著,默認情況下,整型屬性將會被強制?

答案是肯定的。不僅僅是整型,所有的值類型都會被強制,因為它們不能為 Null 值。

如果我們想有一個非 Required 整型域該如何?

把它設置為 Nullable?

public int? Salary{get;set;}

如何特定為 Salary 改變認證信息?

默認情況下,認證是支持 Salary的(因為它是整數類型),不會允許我們改變認證信息。我們可以通過 Regular 表達式、Range 或者是 Custom Validator來同樣達到這個目的。

為什么當認證失敗時,值會被清空?

因為這是一個新的請求。數據入口視圖將會在開始被呈現,并且在呈現之后和發展視圖是一樣的,但是和請求視圖是不一樣的。我們將會在第四天的學習中來學習如何保持值不變。

我們可以明確地讓 Model Binder 來執行嗎?

答案是肯定的。只需要簡單地從 Action 方法中移走參數。默認情況下,它將會停止運行中的默認 Model Binder。

在這種情形下,我們可以運用 UpdateModel 函數如下:

Employee e = new Employee(); UpdateModel<employee>(e);

注:UpdateModel 不會處理原始數據類型。

UpdateModel 方法 和 TryUpdateModel 方法有什么區別?

TryUpdateModel 和 UpdateModel 是一樣的,除了一個附加的優勢。

當 Model 由于任意原因適配失敗時,UpdateModel 將會拋出異常。這種情況下,ModelState.IsValid 函數將不會有任何左右。

TryUpdateModel 是將 Employee 對象和函數參數保持精確地一致。如果更新失敗了,ModelState.IsValid 將會為 False。

客戶端的認證是如何的?

這個可以被手動完成,或者我們可以運用 HTML Helper 類。

我們將會在第四天的學習中探討這兩種手動的客戶端認證方式,以及運用 HTML Helper 來自動客戶端認證。

我們可以為一個屬性附加上多個 DataAnnotation 嗎?

答案是肯定的。在這種情形下,多個認證都會被觸發。

9. 自定義服務器端認證

第一步:創建自定義認證

創建一個新的類,叫做 FirstNameValidation。

public class FirstNameValidation:ValidationAttribute {protected override ValidationResult IsValid(object value, ValidationContext validationContext){if (value == null) // Checking for Empty Value{return new ValidationResult("Please Provide First Name");}else{if (value.ToString().Contains("@")){return new ValidationResult("First Name should contain @");}}return ValidationResult.Success;} }

第二步:向 First Name 中附加認證

打開 Employee 類,然后將 FirstName 屬性的默認的「Required」屬性移走,附加上 FirstNameValidation。

[FirstNameValidation] public string FirstName { get; set; }

第三步:執行并測試

按下 F5,導航到「Employee/AddNew」動作。

  • Test 1

  • Test 2

10. 總結

這里我們完成了第三天的學習。在第四天學習中,我們將會提升項目到一個新的版本。第四天的學習事項如下:

  • 實現客戶端的認證。

  • 理解 HTML Helper。

  • 實現 Authentication。

  • 部分視圖增加 Footers。

原文地址:Learn MVC Project in 7 days

本文由OneAPM工程師編譯 ,想技術文章,請訪問OneAPM官方技術博客。

總結

以上是生活随笔為你收集整理的7 天玩转 ASP.NET MVC — 第 3 天的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。