淺談ASP.NET MVC 3中如何使用Model
昨天博客發(fā)了新文章,講一下我對如何使用MVC中的Model的看法,不是什么大技術(shù),當(dāng)是一個技術(shù)討論^^
原文地址:http://www.youguanbumen.net/Article.aspx?id=79
原文:
前兩天寫了個文章ASP.NET MVC 3 —— Model遠(yuǎn)程驗(yàn)證,主要記錄了一下ASP.NET MVC 3中新增的RemoteAttribute類的使用,得益于這個類,我們可以在模型中為屬性配置客戶端遠(yuǎn)程校驗(yàn)的業(yè)務(wù),文章中給了出一個簡單的實(shí)體類MyUser_Add,舉了一個最常見的注冊用戶時驗(yàn)證用戶名是否存在的例子,最后成功地對用戶名實(shí)現(xiàn)了用ajax加薪校驗(yàn)的功能。給出Model的代碼如下:
- /// <summary>
 - /// 用戶添加操作的模型
 - /// </summary>
 - publicclassMyUser_AddModel
 - {
 - #region MyRegion
 - /// <summary>
 - /// 用戶名
 - /// </summary>
 - [DisplayName("登錄賬號")]
 - [Required(ErrorMessage = "用戶賬號不能為空")]
 - [Remote("CheckUserAccountExists", "Test", ErrorMessage = "用戶賬號已存在")]
 - // 遠(yuǎn)程驗(yàn)證(Ajax)
 - publicstringUserAccount { get; set; }
 - }
 
文章發(fā)到博客園上面之后有朋友提出一了一點(diǎn):“這個我們可以認(rèn)為在創(chuàng)建的時候解決重復(fù)問題,但是如果是Update的話,我相信這樣的語句應(yīng)該也會報錯誤的”。就是說如果這個Model用于做Update操作的時候,校驗(yàn)用戶名是否存在的方法和Add操作會有點(diǎn)不同,因?yàn)橐炎约号懦谕?,例如原來的用戶名?rdquo;user1“修改后還叫”user1“,這時候判斷用戶名是否存在的標(biāo)準(zhǔn)是”如果存在用戶名是‘user1’的并且用戶ID號不是當(dāng)前這個要修改的用戶,那么用戶不可用(存在)“,而Add操作的時候不存在”自己“,所以我看可以理解為兩個操作都需要判斷用戶名是否存在,但是使用了不同的策略!
剛好之前看了ASP.NET MVC 3自帶的Demo(就是創(chuàng)建MVC3.0項(xiàng)目后生成的那個- -?。雽懸幌挛易约赫J(rèn)為的”微軟希望我們怎么去設(shè)計MVC中的Model”的看法,發(fā)現(xiàn)似乎和這個問題有點(diǎn)聯(lián)系,以下是我個人的觀點(diǎn):
首先我們看下Demo項(xiàng)目中Models目錄下的AccountModels.cs,下面的代碼摘自這個文件中的兩個我認(rèn)為很有代表性的類,都是和用戶有關(guān)的,源代碼如下:
- publicclassLogOnModel
 - {
 - [Required]
 - [Display(Name = "User name")]
 - publicstringUserName { get; set; }
 - [Required]
 - [DataType(DataType.Password)]
 - [Display(Name = "Password")]
 - publicstringPassword { get; set; }
 - [Display(Name = "Remember me?")]
 - publicboolRememberMe { get; set; }
 - }
 - publicclassRegisterModel
 - {
 - [Required]
 - [Display(Name = "User name")]
 - publicstringUserName { get; set; }
 - [Required]
 - [DataType(DataType.EmailAddress)]
 - [Display(Name = "Email address")]
 - publicstringEmail { get; set; }
 - [Required]
 - [ValidatePasswordLength]
 - [DataType(DataType.Password)]
 - [Display(Name = "Password")]
 - publicstringPassword { get; set; }
 - [DataType(DataType.Password)]
 - [Display(Name = "Confirm password")]
 - [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
 - publicstringConfirmPassword { get; set; }
 - }
 
注意上面兩個類的類名,我們很容易讀懂一個是“(用戶)登錄模型”,一個是“(用戶)注冊模型”,有意思的地方在于兩個類都用UserName、Password兩個屬性,UserName的驗(yàn)證方式完全一樣,而Password有所不同,RegisterModel中多了一個ValidatePasswordLengthAttribute的特性——一個自定義驗(yàn)證特性。這兩個模型對應(yīng)的是不同的Action-View,于是我的理解是:Model是為了Actioin-View而存在的。例如,有一個頁面是用來顯示一張表單,這張表單會被提交到一個介紹Post請求的Action中,這時候就會創(chuàng)建一個和這個表單對應(yīng)的Model,用來在View和Action中充當(dāng)媒介的作用(所謂的“實(shí)體傳參”)。
回到上面那個檢測用戶名是否存在的問題,基于這個想法可以得出一個解決方案,那就是創(chuàng)建另外一個新類,叫做MyUser_UpdateModel(用戶修改模型),可以得出以下的代碼
- publicclassMyUser_UpdateModel
 - {
 - /// <summary>
 - /// 用戶名
 - /// </summary>
 - [DisplayName("登錄賬號")]
 - [Required(ErrorMessage = "用戶賬號不能為空")]
 - [ValidateUserAccountAttribute] // 自定義驗(yàn)證
 - [Remote("CheckUserAccountExistsForUpdate", "Test", ErrorMessage = "用戶賬號已存在")] // 遠(yuǎn)程驗(yàn)證(Ajax)
 - publicstringUserAccount { get; set; }
 - }
 
注意到遠(yuǎn)程驗(yàn)證調(diào)用的是另外一個Action,這個Action的代碼如下:
- /// <summary>
 - /// 用于驗(yàn)證用戶賬號是否存在的Action(Update操作時使用)
 - /// </summary>
 - /// <param name="UserAccount">用戶賬號</param>
 - /// <returns></returns>
 - [HttpGet]
 - public ActionResult CheckUserAccountExistsForUpdate(string UserAccount)
 - {
 - var ms = ModelState;
 - string[] existsUsers = { "wodanwojun" };
 - bool exists = string.IsNullOrEmpty(existsUsers.FirstOrDefault(u => u.ToLower() == UserAccount.ToLower())) == false;
 - return Json(!exists, JsonRequestBehavior.AllowGet);
 - }
 - public class MyUser_UpdateModel
 - {
 - /// <summary>
 - /// 用戶名
 - /// </summary>
 - [DisplayName("登錄賬號")]
 - [Required(ErrorMessage = "用戶賬號不能為空")]
 - [ValidateUserAccountAttribute] // 自定義驗(yàn)證
 - [Remote("CheckUserAccountExistsForUpdate", "Test", ErrorMessage = "用戶賬號已存在")] // 遠(yuǎn)程驗(yàn)證(Ajax)
 - public string UserAccount { get; set; }
 - }
 
這里假設(shè)要修改的用戶的用戶名叫做“youguanbumen”,所以驗(yàn)證的時候如果輸入了有關(guān)部門是不應(yīng)該提示“該賬號已存在”的(因?yàn)榫褪撬约?,用了這個賬號是沒問題的)??刂破鞯拇a我就不寫咯,大致就是得到一個用戶名叫做“youguanbumen”的Model——MyUser_UpdateModel類,然后通過return View(object model)方法丟給View(當(dāng)然,View是強(qiáng)類型的——MyUser_UpdateModel類),測試結(jié)果截圖如下:
1、輸入“wodanwojun”作為用戶名,發(fā)現(xiàn)通不過,就像下面這張截圖這樣,原因請見上面的代碼!

2、輸入“youguanbumen”作為用戶名。發(fā)現(xiàn)沒有錯誤提示,就像下面這張截圖這樣,原因請見上面的代碼,并對照前一篇文章中另外一個用于遠(yuǎn)程校驗(yàn)的Action的代碼!

總結(jié)一下:似乎寫出來的每一篇文章都不短但是講的東西都很少,呵呵,請別介意^_^。雖然寫代碼的經(jīng)驗(yàn)很不多,但是個人對于代碼還是有一些自己的看法的。選擇一個框架來開發(fā)一個系統(tǒng),就意味著在開發(fā)的過程中你需要遵循某些約定好的東西,例如選擇WebForm來開發(fā)系統(tǒng),就盡量的接受”事件相應(yīng)“和服務(wù)器端控件;選擇了MVC就要接受把C#代碼嵌到頁面去的這個事實(shí),當(dāng)然如果使用了某些RIA框架后可能不出現(xiàn)這種情況(因?yàn)轫撁嫔系臇|西基本都是異步請求回來的)。特別是多人開發(fā)的時候,我們有必要遵循某些套路來寫代碼,例如上面這個例子,也許寫Model、寫View和寫Action是三個不同的人來完成的時候,“如果遵循這一個Action會有一個Model來支持它”的這種套路來走的話,每個人都很容易找到代碼的下手點(diǎn),寫View的人知道如何去聲明頁面為強(qiáng)類型(他會去找相關(guān)的Model),寫Action的人知道return View(object model)中的model是啥,也知道用于處理Post的Action的參數(shù)是什么,寫Model的人需要很了解業(yè)務(wù),知道哪些字段是必填的,那些字段有長度限制等等,但是他也許不知道這個Model會被拿去怎么展示!
ASP.NET MVC中的Model是和業(yè)務(wù)緊密相關(guān)的,有什么樣的業(yè)務(wù)需求就會產(chǎn)生什么樣的Model,并且會有相應(yīng)的Action來出來它,有相應(yīng)的View來展示它。如果基于這個想法來開發(fā)系統(tǒng)的話,很有可能得出這樣一個簡要的開發(fā)流程:研究業(yè)務(wù)-->轉(zhuǎn)化為對應(yīng)的Model,根據(jù)業(yè)務(wù)需求對Model的屬性配置驗(yàn)證特性-->設(shè)計數(shù)據(jù)庫表來對數(shù)據(jù)進(jìn)行存放(也許是xml也不一定)-->設(shè)計View來展示它,設(shè)計Action來處理它......。
原文鏈接:http://www.cnblogs.com/serafin/archive/2011/01/27/1945934.html
 
2009-07-22 13:24:24
 
 
 














 
 
 