【第二篇】ASP.NET MVC快速入門之資料註解(MVC5+EF6)

來源:互聯網
上載者:User

標籤:不能   pre   空間   資料   類比post   菜單   入門   文章   狀態   

目錄

【第一篇】ASP.NET MVC快速入門之資料庫操作(MVC5+EF6)

【第二篇】ASP.NET MVC快速入門之資料註解(MVC5+EF6)

【第三篇】ASP.NET MVC快速入門之安全性原則(MVC5+EF6)

【第四篇】ASP.NET MVC快速入門之完整樣本(MVC5+EF6)

【番外篇】ASP.NET MVC快速入門之免費jQuery控制項陳列庫(MVC5+EF6)

 

請關注三石的部落格:http://cnblogs.com/sanshi

 

 

資料庫連接字串

上一篇文章中,我們使用MVC的模板自動產生了CRUD的全部操作,但是沒有設定資料庫連接字串,那麼資料存到什麼地方了?

 

開啟項目的App_Data目錄,你可以探索資料庫原來在這裡:

 

我們通過VS內建的資料庫訪問工具,來看下錶結構和其中的資料,首先找到[伺服器總管]面板,新增資料庫連接:

 

在添加取得連線精靈對話方塊中,輸入伺服器名:(LocalDb)\MSSQLLocalDB,這個是VS2015內建的LocalDb的伺服器執行個體名稱(如果你使用VS2013,這個名稱可能是:(LocalDB)\v11.0)。資料庫選擇我們剛剛建立的StudentDbContext。

 

原來如果沒有顯式的指定資料庫連接字串,VS會使用預設的LocalDb執行個體,這個對應關係在Web.config中有定義:

 
<entityFramework>       <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">         <parameters>              <parameter value="mssqllocaldb" />         </parameters>       </defaultConnectionFactory>       <providers>         <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />       </providers></entityFramework>
 

 

 

當然我們也可以明確指定資料庫連接字串:

 
<connectionStrings>       <add name="DefaultConnection"connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\AspNetMvc.QuickStart.Models.StudentDbContext.mdf;Initial Catalog=AspNetMvc.QuickStart.Models.StudentDbContext;Integrated Security=True"         providerName="System.Data.SqlClient" /></connectionStrings>
 

 

 

然後在代碼中引用這個資料庫連接字串:

 
public class StudentDbContext : DbContext{       public StudentDbContext() : base("DefaultConnection")       {       }        public DbSet<Student> Students { get; set; }}
 

 

 

注意:如果使用的VS2013,Data Source應該是(LocalDb)\v11.0,而VS2015對應的是(LocalDb)\MSSQLLocalDB。

 

經過這個改變,在真正部署到MSSQL伺服器時,簡單修改資料庫連接字串就可以了。

 

資料庫表結構

開啟Students的表定義:

 

可以看下EF是怎麼將Student模型映射到資料庫表結構的:

  1. 模型中ID屬性的資料對應為表的主鍵。
  2. 模型中的string類型映射為表的nvarchar(MAX)。
  3. 模型中的int和DateTime分別映射為表的int和datetime類型。

 

再來看下上一篇文章中添加到表中的資料:

 

如果你之前有資料庫設計的經驗,會很容易發現這個表結構的問題:

  1. Name和Major儲存字串,一般需要限制最大長度,比如nvarchar(200)。
  2. Name和Major列應該不允許為空白。

 

那麼怎麼來實現這兩個需求呢?直接修改資料庫肯定是不行的!

 

資料註解

我們應該從模型入手,還記得我們在上一篇文章結尾說的那句話嗎,資料模型不僅會影響資料庫的表結構,還會控制MVC視圖層的用戶端驗證和控制器層的伺服器端驗證。

 

修改Student模型類,添加適當的資料註解:

 
public class Student{       public int ID { get; set; }        [Required]       [StringLength(200)]       public string Name { get; set; }        public int Gender { get; set; }        [Required]       [StringLength(200)]       public string Major { get; set; }        public DateTime EntranceDate { get; set; }}
 

 

 

如果輸入[Required]時沒有智能感知,很可能是沒有引用相應的命名空間,VS可以很方便的協助我們添加:

 

這樣就會在檔案頭部添加如下引用:

using System.ComponentModel.DataAnnotations;

 

 

直接運行項目(Ctrl+F5),此時我們會看到如下的錯誤頁面:

 

相信使用EF的同學都會遇到這個頁面,上面的提示也很明確,包含兩個層次的資訊:

  1. 資料庫建立之後模型改變了。
  2. 可以使用資料移轉來更新資料庫。

 

資料移轉(Migrations)

從VS的[工具]菜單中,找到Nuget包管理器控制台:

 

 

啟用資料移轉

在控制台中輸入如下命令:Enable-Migrations

 

這時會在項目目錄中增加一個Migrations檔案夾,裡面放置了兩個檔案:

 

EF會通過C#代碼的方式將每一次對模型的修改儲存到這個檔案夾中,現在來看下產生的檔案內容:

 

每個遷移檔案,都包含Up和Down兩個重寫函數,分別對應於更新和回退。上面的代碼也很直白,Up函數中建立一個Students表,定義表結構並指定ID主鍵(PrimaryKey),Down函數用來後援動作,裡面簡單的刪除了Students表。

 

可以看到,這裡的建立表操作並沒有使用最新的模型(Name列沒有nullable的設定),因為這是初始模型對應的表結構,EF會在資料庫中自動產生一個名為__MigrationHistory表來追蹤資料庫的狀態。

 

增加遷移項

增加遷移項需要我們手工來進行,在封裝管理員控制台中,輸入如下命令:

Add-Migration Add_Annotation_Name_Major

 

這時會在Migrations目錄下產生遷移檔案,檔案是以[時間+遷移名]命名的,方便尋找:

201612160406415_Add_Annotation_Name_Major.cs

 

更新到資料庫

此時,資料庫尚未改變,我們還需要手工命令來更新資料庫:

Update-Database

 

此時,再來查看資料庫中Students的表結構:

 

Name列的資料類型和是否允許Null都已經改變了。

 

在真實的項目中,資料庫可能部署在遠程伺服器中,這時我們就不能直接在VS中通過Update-Database來更新資料庫了。

不過我們可以產生更新SQL指令碼,然後拿到資料庫伺服器上執行。產生這個SQL指令碼的方法:

Update-Database   -Script

-SourceMigration: InitialCreate

-TargetMigration: Add_Annotation_Name_Major

 

來看下產生的SQL更新指令碼:

 

有了這個SQL更新指令碼,我們就可以方便的更新遠端資料庫了。

 

視圖的用戶端驗證

現在運行項目,轉到建立頁面:

可以看到,如果Name為空白則會有錯誤提示資訊,而Major輸入字串過多,也會有提示資訊,而這些設定是來自模型的資料註解。

 

這個用戶端驗證是有jQuery的validation外掛程式提供的:

http://bassistance.de/jquery-plugins/jquery-plugin-validation/

 

如果你查看頁面原始碼,會發現Major輸入框的input標籤上有相應的自訂屬性data-val-length-max=200和data-val-length,而這些屬性值正是來自於模型的資料註解。

 

控制器的伺服器端驗證

在啟用JavaScript的情況下,由於所有的錯誤輸入在用戶端就會被攔截,所以根本到達不了伺服器,不過這並不表示惡意使用者無法提交錯誤的輸入,有很多種方法可以做到:

 

禁用JavaScript

不同瀏覽器禁用JavaScript的方法不同,在Chrome中,F12開啟開發工具,然後找到設定對話方塊:

 

 

此時提交頁面,你會看到和前面完全相同的頁面,由於本地運行速度很快,你甚至可能沒意識已經發起了一次HTTP POST請求,而顯示錯誤提示的頁面來自伺服器,而不是用戶端:

 

響應本文包含如下內容,其中錯誤資訊是伺服器端產生的:

 
<div class="form-group">       <label class="control-label col-md-2" for="Name">Name</label>       <div class="col-md-10">              <input class="input-validation-error form-control text-box single-line" data-val="true" data-val-length="欄位 Name 必須是最大長度為 200 的字串。" data-val-length-max="200" data-val-required="Name 欄位是必需的。" id="Name" name="Name" type="text" value="" />              <span class="field-validation-error text-danger" data-valmsg-for="Name" data-valmsg-replace="true">Name 欄位是必需的。</span>       </div></div>
 

 

 

此時再回過頭來看下Students控制器中Create操作方法的定義:

 
[HttpPost][ValidateAntiForgeryToken]public ActionResult Create([Bind(Include = "ID,Name,Gender,Major,EntranceDate")] Student student){       if (ModelState.IsValid)       {              db.Students.Add(student);              db.SaveChanges();              return RedirectToAction("Index");       }        return View(student);}
 

 

 

如果驗證失敗,則不更新資料庫,並返回帶Student模型的視圖。

 

類比POST請求

有很多工具可以類比POST,這裡我們講解如果使用Fiddler來類比項伺服器提交POST請求。

開啟Fiddler,就開始自動監測所有的HTTP請求,這時我們重新整理Create頁面,並在JavaScript禁用的情況下,提交表單,這時會有兩個請求:

 

首先選中左側的第二個請求,右側面板中選擇Inspectors->WebForms,下面會顯示三個窗格:

  1. QueryString:當前請求的URL查詢字串。
  2. Body:POST請求的表單參數。
  3. 第三部分:響應本文,我們可以看到伺服器端返回的錯誤資訊。

 

現在切換到Composer選項卡,我們可以在這裡面類比POST請求:

 

上面有一段提示資訊:使用這個頁面建立一個請求。你可以通過拖拽的方式從左側會話列表中拷貝一個之前的請求。

 

這就方便多了,我們從左側選中第二個請求並拖拽到本頁面:

 

這時頁面背景變成明顯的綠色以作提示,拖拽結束:

 

這時,Fiddler自動幫我們設定了類比POST請求的參數,拷貝自之前的某個請求,這時的[Request Body]是經過URL編碼的,我們可以方便的進行解碼:

 

我們把這段代碼修改成:

__RequestVerificationToken=wwoxICDootbixw8YMiFIOU1WW95QSCicREsWLeewlSAE28sdyEA0ZChlY0nfuOlxu2WDIjcrx086GYkaBOAtewyARWbeRZp0kD6tRt-hyAs1&Name=張三石&Gender=1&Major=&EntranceDate=2000-09-01

 

把這段字串拷貝到Fiddler中的[Request Body],並點擊[Execute]按鈕,這時會發起一個新的類比請求:

 

注意這個請求並不是從頁面發出的,而是通過工具類比的HTTP POST請求,並且我們還修改了其中的表單參數(Name=張三石,Major=Null 字元串),這樣當然也就會躲開瀏覽器端的JavaScript驗證規則,但是還是無法穿透伺服器端的驗證。

 

這也正是MVC中資料註解帶來的便利,一個地方定義,三個地方使用(資料庫表結構、用戶端驗證,伺服器端驗證)。

 

小結

本章我們首先查看了EF自動產生的資料庫結構,然後為資料模型添加資料註解,繼而介紹了資料移轉的工作過程。資料註解不僅對資料庫表結構產生影響,而且會應用到前台的用戶端驗證和伺服器端驗證,接下來我們詳細講解了兩則躲避用戶端驗證的手段,分別為禁用JavaScript和類比POST請求。從而更加深刻的認識到資料註解給我們提供的便利:一個地方定義,三個地方使用(資料庫表結構、用戶端驗證,伺服器端驗證)

在建立新使用者頁面,我們可以看到兩個安全相關的代碼(ValidateAntiForgeryToken和Bind),它們分別用於阻止CSRF跨站請求偽造和Over-Posting過多提交攻擊,下一篇文章我們會詳細介紹。

下載樣本原始碼

 

【第二篇】ASP.NET MVC快速入門之資料註解(MVC5+EF6)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.