自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用Visual Studio 2010和MVC 2.0增強(qiáng)驗(yàn)證功能

開(kāi)發(fā) 后端
本篇文章主要關(guān)注使用DataAnnotations來(lái)對(duì)model進(jìn)行驗(yàn)證,同時(shí)會(huì)對(duì)最新版本特性進(jìn)行簡(jiǎn)單的接觸,以及如何使用Visual Studio 2010和MVC 2.0增強(qiáng)驗(yàn)證功能。

在開(kāi)始之前,我不得不說(shuō)明我已經(jīng)安裝了Visual Studio 2010 RC1,并使用它將老版本轉(zhuǎn)換為ASP.Net 4.0,大多數(shù)情況下,當(dāng)你接收到來(lái)自用戶(hù)從form表單post來(lái)的信息后,你的驗(yàn)證代碼往往會(huì)檢查相應(yīng)的值是否存在,數(shù)據(jù)類(lèi)型是否正確以及數(shù)據(jù)的范圍是否正確。

如果將驗(yàn)證代碼放到一個(gè)集中的地方時(shí),那類(lèi)似上面所說(shuō)的改變會(huì)不會(huì)變得更簡(jiǎn)單些?Model中的DataAnnotations正是為此而來(lái),在MVC 2.0中,這一特性被包含在內(nèi)。

DataAnnotations作為.net Framework的一部分已經(jīng)有一段時(shí)間了,但是MVC 2.0中增加了ModelMetaData類(lèi),這是儲(chǔ)存MetaData的容器,默認(rèn)會(huì)使用同樣也是新增類(lèi)的DataAnnotationsMetaDataProvider類(lèi)。因?yàn)閭魅氲闹禃?huì)由Action方法接受model binding作為匹配傳入?yún)?shù)和action的參數(shù)而介入。

在MVC 2.0中,默認(rèn)的model binder使用DataAnnotationsMetaDataProvider來(lái)獲取metadata中model binder嘗試匹配的對(duì)象,如果驗(yàn)證用的metadata存在,則其會(huì)通過(guò)對(duì)對(duì)象的屬性和傳入的值比較來(lái)進(jìn)驗(yàn)證,這類(lèi)meta由你通過(guò)使用標(biāo)簽(Attribute)修飾屬性來(lái)實(shí)現(xiàn)。

下面例子中我通過(guò)原程序中添加聯(lián)系人這一過(guò)程來(lái)描述使用DataAnnotatioins的方法,這里我們使用自定義ViewModel,名為:ContactPersonViewModel。通過(guò)Contact.Add()這個(gè)action方法來(lái)添加聯(lián)系人,代碼如下:

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Web.Mvc;  
  4. using System.ComponentModel;  
  5.  
  6. namespace ContactManagerMVC.Views.ViewModels  
  7. {  
  8.   public class ContactPersonViewModel  
  9.   {  
  10.     public int Id { get; set; }  
  11.     public string FirstName { get; set; }  
  12.     public string MiddleName { get; set; }  
  13.     public string LastName { get; set; }  
  14.     public DateTime DateOfBirth { get; set; }  
  15.     public IEnumerable<SelectListItem> Type { get; set; }  
  16.   }  
  17. }  

下面,我在為屬性添加一些標(biāo)簽(Attribute):

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Web.Mvc;  
  4. using System.ComponentModel.DataAnnotations;  
  5. using ContactManagerMVC.Attributes;  
  6. using System.ComponentModel;  
  7.  
  8. namespace ContactManagerMVC.Views.ViewModels  
  9. {  
  10.   public class ContactPersonViewModel  
  11.   {  
  12.     public int Id { get; set; }  
  13.     [Required(ErrorMessage = "Please provide a First Name!")]  
  14.     [StringLength(25, ErrorMessage = "First name must be less than 25 characters!")]  
  15.     [DisplayName("First Name")]  
  16.     public string FirstName { get; set; }  
  17.  
  18.     [DisplayName("Middle Name")]  
  19.     public string MiddleName { get; set; }  
  20.  
  21.     [Required(ErrorMessage = "Please provide a Last Name!")]  
  22.     [StringLength(25, ErrorMessage = "Last name must be less than 25 characters!")]  
  23.     [DisplayName("Last Name")]  
  24.     public string LastName { get; set; }  
  25.  
  26.     [Required(ErrorMessage = "You must provide a Date Of Birth!")]  
  27.     [BeforeTodaysDate(ErrorMessage = "You can't add someone who hasn't been born yet!")]  
  28.     [DisplayName("Date Of Birth")]  
  29.     public DateTime? DateOfBirth { get; set; }  
  30.  
  31.     public IEnumerable<SelectListItem> Type { get; set; }  
  32.   }  
  33. }  

上面標(biāo)簽的絕大多數(shù)標(biāo)簽都是在System.ComponentModel.Annotations命名空間內(nèi),只有RequiredAttribute標(biāo)簽不在此命名空間內(nèi),這個(gè)標(biāo)簽聲明此值必須是一個(gè)有效值,并且包含ErrorMessage屬性。這個(gè)屬性可以讓你傳入自定義錯(cuò)誤信息。StringLengthAttribute標(biāo)簽指定了屬性可以接受的最小值和***值范圍。當(dāng)和RequiredAttribute標(biāo)簽結(jié)合使用時(shí),只需要設(shè)置可以接受的***值。DisplayNameAttribute用于設(shè)置屬性如何顯示。#p#

上面標(biāo)簽中BeforeTodaysDateAttribute標(biāo)簽并不是.net Framework所提供,這是一個(gè)自定義標(biāo)簽,用于檢測(cè)日期是否比當(dāng)前的日期要早,你可以看到ErrorMessage值被設(shè)置。這個(gè)標(biāo)簽用于防止任何被添加到聯(lián)系人列表的聯(lián)系人還未出生,下面是這個(gè)標(biāo)簽的代碼:

  1. using System.ComponentModel.DataAnnotations;  
  2. using System;  
  3.  
  4. namespace ContactManagerMVC.Attributes  
  5. {  
  6.   public class BeforeTodaysDateAttribute : ValidationAttribute  
  7.   {  
  8.     public override bool IsValid(object value)  
  9.     {  
  10. if (value == null)  
  11. {  
  12.   return true;  
  13. }  
  14. DateTime result;  
  15. if (DateTime.TryParse(value.ToString(), out result))  
  16. {  
  17.   if (result < DateTime.Now)  
  18.   {  
  19.     return true;  
  20.   }  
  21. }  
  22. return false;  
  23.     }  
  24.   }  
  25. }  

很簡(jiǎn)單是吧,這個(gè)類(lèi)繼承了ValidationAttribute并重寫(xiě)了IsValid()虛方法,如果未提供值,或是值小于當(dāng)前日期(DateTime.Now),則返回True.利用標(biāo)簽(Attribute)的方式讓在一個(gè)集中的地方應(yīng)用驗(yàn)證規(guī)則變得簡(jiǎn)單,現(xiàn)在,只要ContactPersonViewModel在程序中被用到了,則驗(yàn)證規(guī)則同時(shí)也會(huì)被應(yīng)用到。但現(xiàn)在DefaultModelBinder內(nèi)的DataAnnotations被支持,下面來(lái)看新版本的Add Partial View:

  1. <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ContactPersonViewModel>" %> 
  2.  
  3. <script type="text/javascript"> 
  4.   $(function() {  
  5.   $('#DateOfBirth').datepicker({ dateFormat: 'yy/mm/dd' });  
  6.   });  
  7.   $('#save').click(function () {  
  8. $.ajax({  
  9.     type: "POST",  
  10.     url: $("#AddContact").attr('action'),  
  11.     data: $("#AddContact").serialize(),  
  12.     dataType: "text/plain",  
  13.     success: function (response) {  
  14.   if (response == "Saved") {  
  15. window.location = "/";   
  16.   }else {  
  17. $("#details").html(response);  
  18.   }  
  19.     }  
  20. });  
  21.   });  
  22. </script> 
  23.  
  24. <% using (Html.BeginForm("Add", "Contact", FormMethod.Post, new { id = "AddContact" }))  
  25.    {%> 
  26. <table> 
  27.   <tr> 
  28. <td class="LabelCell"><%= Html.LabelFor(m => m.FirstName)%> </td> 
  29. <td><%= Html.TextBox(m => m.FirstName)%>   
  30. <%= Html.ValidationMessageFor(m => m.FirstName)%></td>    
  31.   </tr> 
  32.   <tr> 
  33. <td class="LabelCell"><%= Html.LabelFor(m => m.MiddleName)%> </td> 
  34. <td><%= Html.TextBox(m => m.MiddleName)%></td>    
  35.   </tr> 
  36.   <tr> 
  37. <td class="LabelCell"><%= Html.LabelFor(m => m.LastName)%> </td> 
  38. <td><%= Html.TextBox(m => m.LastName)%>   
  39. <%= Html.ValidationMessageFor(m => m.LastName)%></td>    
  40.   </tr> 
  41.   <tr> 
  42. <td class="LabelCell"><%= Html.LabelFor(m => m.DateOfBirth)%> </td> 
  43. <td><%= Html.TextBox(m => m.DateOfBirth)%>   
  44. <%= Html.ValidationMessageFor(m => m.DateOfBirth)%></td>    
  45.   </tr> 
  46.   <tr> 
  47.     <td class="LabelCell"><%= Html.LabelFor(m => m.Type)%></td> 
  48.     <td><%= Html.DropDownList("Type")%> 
  49.     </td> 
  50.   </tr> 
  51.   <tr> 
  52.     <td class="LabelCell"></td> 
  53.     <td><input type="button" name="save" id="save" value="Save" /></td> 
  54.   </tr> 
  55. </table> 
  56. <% } %>  

可以看出,這里使用新的強(qiáng)類(lèi)型Html Helper.對(duì)前面項(xiàng)目修改的兩處是利用了jQuery代碼。***處是添加聯(lián)系人的Partial View是通過(guò)AJax提交,如果驗(yàn)證失敗,則添加的form會(huì)再次被顯示,如果驗(yàn)證通過(guò),新的聯(lián)系人被添加到列表中,頁(yè)面會(huì)刷新繼而顯示更新后包含新聯(lián)系人的列表。

由于下面幾種原因,原來(lái)的Action方法需要被修正。首先修改action方法使其接受ContactPersonViewModel而不是ContactPerson作為參數(shù),這是因?yàn)橄嚓P(guān)的驗(yàn)證規(guī)則應(yīng)用于ContactPersonViewModel,如果不將參數(shù)類(lèi)型改變,那model binder依然能將傳入的值和ContactPerson的屬性相匹配,但所有的驗(yàn)證規(guī)則就不復(fù)存在了。第二個(gè)改變是檢查ModelState的IsValid屬性是否有效,否則整個(gè)驗(yàn)證就變得毫無(wú)意義.

  1. [AcceptVerbs(HttpVerbs.Post)]  
  2. public ActionResult Add([Bind(Exclude = "Id, Type")]ContactPersonViewModel person)  
  3. {  
  4.  
  5.     if (ModelState.IsValid)  
  6.     {  
  7.   var p = new ContactPerson  
  8.   {  
  9. FirstName = person.FirstName,  
  10. MiddleName = person.MiddleName,  
  11. LastName = person.LastName,  
  12. Type = Request.Form["Type"].ParseEnum<PersonType>()  
  13.   };  
  14.   if (person.DateOfBirth != null)  
  15. p.DateOfBirth = (DateTime)person.DateOfBirth;  
  16.   ContactPersonManager.Save(p);  
  17.   return Content("Saved");  
  18.     }  
  19.     var personTypes = Enum.GetValues(typeof(PersonType))  
  20.     .Cast<PersonType>()  
  21.     .Select(p => new  
  22.     {  
  23.   ID = p,  
  24.   Name = p.ToString()  
  25.     });  
  26.     person.Type = new SelectList(personTypes, "ID", "Name");  
  27.     return PartialView(person);  
  28. }   
  29.  

在model綁定過(guò)程中,我去掉了id和Type屬性,因?yàn)樵诎崖?lián)系人添加到數(shù)據(jù)庫(kù)以前并不會(huì)存在id屬性,而去掉Type屬性是因?yàn)樵赩iewModel中它的類(lèi)型是SelectList,但在BLL層中ContactPerson對(duì)象中卻是枚舉類(lèi)型,如果ModelState的IsValid屬性為T(mén)rue(注:既驗(yàn)證通過(guò)),則ViewModel的屬性會(huì)和ContactPerson對(duì)象的屬性進(jìn)行匹配,如果IsValid不為T(mén)rue,數(shù)據(jù)會(huì)回傳到View中顯示驗(yàn)證失敗的相關(guān)信息。

上面代碼中我們注意到了Request.Form[“Type”]這個(gè)string類(lèi)型的ParseEnum<T>擴(kuò)展方法,這也是為什么我去掉Type屬性,只有這樣它才會(huì)被轉(zhuǎn)換為適當(dāng)?shù)念?lèi)型。擴(kuò)展方法的原型(在我的Google Analytics 文中)如下:

  1. public static T ParseEnum<T>(this string token)  
  2. {  
  3.     return (T)Enum.Parse(typeof(T), token);  
  4. }  
  5.  
  6. edit  

這個(gè)action方法也是如此,除了對(duì)DateOfBirth進(jìn)行編輯那部分:

  1. <tr> 
  2.   <td class="LabelCell"><%= Html.LabelFor(m => m.DateOfBirth)%> </td> 
  3.   <td><%= Html.EditorFor(m => m.DateOfBirth)%>   
  4. <%= Html.ValidationMessageFor(m => m.DateOfBirth)%></td>    
  5. </tr>  

這里我并沒(méi)有使用TextBoxFor<T>擴(kuò)展方法,而是使用了EditorFor<T>方法,默認(rèn)情況下,DateTime類(lèi)型都以hh:mm:ss這樣的方式顯示,但我并不喜歡這種格式,所以我創(chuàng)建了一個(gè)格式化顯示時(shí)間日期的模板,在View/Shared目錄下,我添加了一個(gè)名為EditorTemplates(這也是MVC中應(yīng)有命名方式,因?yàn)镸VC會(huì)自動(dòng)搜索這個(gè)位置)并在此目錄下添加一個(gè)名為DateTime的Partial View,這也是MVC的慣例,而DateTime.ascx的代碼如下:

  1. <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime?>" %> 
  2. <%= Html.TextBox("", Model.HasValue ? Model.Value.ToShortDateString() : string.Empty) %> 

雖然只有短短兩行代碼,但是可以讓時(shí)間日期如果為空時(shí),什么都不顯示,而如果時(shí)間存在,則以ShortDate的格式顯示。

總結(jié)

本篇文章研究了ASP.Net MVC 2.0中利用DataAnnotations來(lái)進(jìn)行驗(yàn)證,現(xiàn)在這已經(jīng)是.net framework的一部分。文中還簡(jiǎn)單的接觸了新版本中的一些特性,包括強(qiáng)類(lèi)型的HTML Helper以及模板。本篇文章的代碼使用Visual Studio 2010 RC1創(chuàng)建的,所以代碼不能在VWD和Visual Studio的環(huán)境中調(diào)試。

Visual Studio 2010 全球發(fā)布會(huì)

【編輯推薦】

  1. 升級(jí)Visual Studio 2010和.Net 4注意要點(diǎn)
  2. 專(zhuān)家揭秘Visual Basic 2010的十大新特性
  3. Visual Studio 2010 Ultimate中MSF過(guò)程模型設(shè)計(jì)
  4. Visual Studio 2010代碼編譯器特性分析
  5. 詳解Visual Studio 2010五大新特性
責(zé)任編輯:王曉東 來(lái)源: 博客園
相關(guān)推薦

2010-02-26 09:18:24

Visual Stud

2010-04-12 08:43:45

Visual Stud

2023-09-26 00:24:44

VisualStudio視圖

2009-10-22 09:47:33

Visual Stud

2009-04-23 14:05:28

Visual Stud歷史調(diào)試功能

2010-09-25 08:50:00

Visual Stud

2009-03-17 08:56:57

Visual StudVS2010C++

2009-12-02 09:43:38

Visual Stud

2009-08-26 09:26:04

Visual Stud

2009-08-21 13:29:20

Visual Stud

2009-11-19 10:55:33

Visual Stud

2009-11-10 13:43:37

Visual Stud

2010-03-16 14:32:16

Visual Stud

2009-12-01 19:12:41

Visual Stud

2009-12-02 10:44:30

Visual Stud

2009-11-19 09:59:47

Visual Stud

2010-04-15 08:40:00

UML建模Visual Stud

2009-10-19 09:48:24

Visual Stud

2010-02-23 10:39:43

Visual Stud

2010-02-04 09:17:26

Visual Stud
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)