天天看點

一起談.NET技術,ASP.NET MVC 3 —— Model的使用?

  昨天部落格發了新文章,講一下我對如何使用MVC中的Model的看法,不是什麼大技術,當是一個技術讨論^^

  原文位址:http://www.youguanbumen.net/Article.aspx?id=79

  原文:

  前兩天寫了個文章ASP.NET MVC 3 —— Model遠端驗證,主要記錄了一下ASP.NET MVC 3中新增的RemoteAttribute類的使用,得益于這個類,我們可以在模型中為屬性配置用戶端遠端校驗的業務,文章中給了出一個簡單的實體類MyUser_Add,舉了一個最常見的注冊使用者時驗證使用者名是否存在的例子,最後成功地對使用者名實作了用ajax加薪校驗的功能。給出Model的代碼如下:

1. /// summary

2. /// 使用者添加操作的模型

3. /// /summary

4. publicclassMyUser_AddModel

5. {

6. #region MyRegion

7. /// summary

8. /// 使用者名

9. /// /summary

10. [DisplayName("登入賬号")]

11. [Required(ErrorMessage = "使用者賬号不能為空")]

12. [Remote("CheckUserAccountExists", "Test", ErrorMessage = "使用者賬号已存在")]

13. // 遠端驗證(Ajax)

14. publicstringUserAccount { get; set; }

15. }

  文章發到部落格園上面之後有朋友提出一了一點:這個我們可以認為在建立的時候解決重複問題,但是如果是Update的話,我相信這樣的語句應該也會報錯誤的。就是說如果這個Model用于做Update操作的時候,校驗使用者名是否存在的方法和Add操作會有點不同,因為要把自己排除在外,例如原來的使用者名叫user1修改後還叫user1,這時候判斷使用者名是否存在的标準是如果存在使用者名是user1的并且使用者ID号不是目前這個要修改的使用者,那麼使用者不可用(存在),而Add操作的時候不存在自己,是以我看可以了解為兩個操作都需要判斷使用者名是否存在,但是使用了不同的政策!

  剛好之前看了ASP.NET MVC 3自帶的Demo(就是建立MVC3.0項目後生成的那個- -!),想寫一下我自己認為的微軟希望我們怎麼去設計MVC中的Model的看法,發現似乎和這個問題有點聯系,以下是我個人的觀點:

  首先我們看下Demo項目中Models目錄下的AccountModels.cs,下面的代碼摘自這個檔案中的兩個我認為很有代表性的類,都是和使用者有關的,源代碼如下:

1. publicclassLogOnModel

2. {

3. [Required]

4. [Display(Name = "User name")]

5. publicstringUserName { get; set; }

6. [Required]

7. [DataType(DataType.Password)]

8. [Display(Name = "Password")]

9. publicstringPassword { get; set; }

10. [Display(Name = "Remember me?")]

11. publicboolRememberMe { get; set; }

12. }

13. publicclassRegisterModel

14. {

15. [Required]

16. [Display(Name = "User name")]

17. publicstringUserName { get; set; }

18. [Required]

19. [DataType(DataType.EmailAddress)]

20. [Display(Name = "Email address")]

21. publicstringEmail { get; set; }

22. [Required]

23. [ValidatePasswordLength]

24. [DataType(DataType.Password)]

25. [Display(Name = "Password")]

26. publicstringPassword { get; set; }

27. [DataType(DataType.Password)]

28. [Display(Name = "Confirm password")]

29. [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]

30. publicstringConfirmPassword { get; set; }

31. }

  注意上面兩個類的類名,我們很容易讀懂一個是(使用者)登入模型,一個是(使用者)注冊模型,有意思的地方在于兩個類都用UserName、Password兩個屬性,UserName的驗證方式完全一樣,而Password有所不同,RegisterModel中多了一個ValidatePasswordLengthAttribute的特性——一個自定義驗證特性。這兩個模型對應的是不同的Action-View,于是我的了解是:Model是為了Actioin-View而存在的。例如,有一個頁面是用來顯示一張表單,這張表單會被送出到一個介紹Post請求的Action中,這時候就會建立一個和這個表單對應的Model,用來在View和Action中充當媒介的作用(所謂的實體傳參)。

  回到上面那個檢測使用者名是否存在的問題,基于這個想法可以得出一個解決方案,那就是建立另外一個新類,叫做MyUser_UpdateModel(使用者修改模型),可以得出以下的代碼

1. publicclassMyUser_UpdateModel

3. /// summary

4. /// 使用者名

5. /// /summary

6. [DisplayName("登入賬号")]

7. [Required(ErrorMessage = "使用者賬号不能為空")]

8. [ValidateUserAccountAttribute] // 自定義驗證

9. [Remote("CheckUserAccountExistsForUpdate", "Test", ErrorMessage = "使用者賬号已存在")]

// 遠端驗證(Ajax)

10. publicstringUserAccount { get; set; }

11. }

  注意到遠端驗證調用的是另外一個Action,這個Action的代碼如下:

1. /// summary

2. /// 用于驗證使用者賬号是否存在的Action(Update操作時使用)

4. /// param name="UserAccount"使用者賬号/param

5. /// returns/returns

6. [HttpGet]

7. public ActionResult CheckUserAccountExistsForUpdate(string UserAccount)

8. {

9. var ms = ModelState;

10. string[] existsUsers = { "wodanwojun" };

11. bool exists = string.IsNullOrEmpty(existsUsers.FirstOrDefault(u = u.ToLower() == UserAccount.ToLower())) == false;

12. return Json(!exists, JsonRequestBehavior.AllowGet);

13. }

14.

15.

16.

17.

18. public class MyUser_UpdateModel

19. {

20. /// summary

21. /// 使用者名

22. /// /summary

23. [DisplayName("登入賬号")]

24. [Required(ErrorMessage = "使用者賬号不能為空")]

25. [ValidateUserAccountAttribute] // 自定義驗證

26. [Remote("CheckUserAccountExistsForUpdate", "Test", ErrorMessage = "使用者賬号已存在")] // 遠端驗證(Ajax)

27. public string UserAccount { get; set; }

28. }

  這裡假設要修改的使用者的使用者名叫做youguanbumen,是以驗證的時候如果輸入了有關部門是不應該提示該賬号已存在的(因為就是他自己,用了這個賬号是沒問題的)。控制器的代碼我就不寫咯,大緻就是得到一個使用者名叫做youguanbumen的Model——MyUser_UpdateModel類,然後通過return View(object model)方法丢給View(當然,View是強類型的——MyUser_UpdateModel類),測試結果截圖如下:

  1、輸入wodanwojun作為使用者名,發現通不過,就像下面這張截圖這樣,原因請見上面的代碼!

一起談.NET技術,ASP.NET MVC 3 —— Model的使用?

  2、輸入youguanbumen作為使用者名。發現沒有錯誤提示,就像下面這張截圖這樣,原因請見上面的代碼,并對照前一篇文章中另外一個用于遠端校驗的Action的代碼! 

一起談.NET技術,ASP.NET MVC 3 —— Model的使用?

  總結一下:似乎寫出來的每一篇文章都不短但是講的東西都很少,呵呵,請别介意^_^。雖然寫代碼的經驗很不多,但是個人對于代碼還是有一些自己的看法的。選擇一個架構來開發一個系統,就意味着在開發的過程中你需要遵循某些約定好的東西,例如選擇WebForm來開發系統,就盡量的接受事件相應和伺服器端控件;選擇了MVC就要接受把C#代碼嵌到頁面去的這個事實,當然如果使用了某些RIA架構後可能不出現這種情況(因為頁面上的東西基本都是異步請求回來的)。

  特别是多人開發的時候,我們有必要遵循某些套路來寫代碼,例如上面這個例子,也許寫Model、寫View和寫Action是三個不同的人來完成的時候,如果遵循這一個Action會有一個Model來支援它的這種套路來走的話,每個人都很容易找到代碼的下手點,寫View的人知道如何去聲明頁面為強類型(他會去找相關的Model),寫Action的人知道return View(object model)中的model是啥,也知道用于處理Post的Action的參數是什麼,寫Model的人需要很了解業務,知道哪些字段是必填的,那些字段有長度限制等等,但是他也許不知道這個Model會被拿去怎麼展示!

  ASP.NET MVC中的Model是和業務緊密相關的,有什麼樣的業務需求就會産生什麼樣的Model,并且會有相應的Action來出來它,有相應的View來展示它。如果基于這個想法來開發系統的話,很有可能得出這樣一個簡要的開發流程:研究業務--轉化為對應的Model,根據業務需求對Model的屬性配置驗證特性--設計資料庫表來對資料進行存放(也許是xml也不一定)--設計View來展示它,設計Action來處理它......。

繼續閱讀