mvc架構中有個聽起來很不錯的功能,那就是在form提交後,能夠自動給實體賦值,只要屬性名稱和html的元素名相同即可,基本上能夠實現常見的實體內容綁定,修改等等,而且還具備自動的表單錯誤驗證功能。如此強大的功能,應該能使開發更有效率,但在使用方面還是有些小麻煩。
mvc架構中將form的values自動賦值到實體中的主要調用方法是TryUpdateModel,關鍵的輔助類是FormCollection。大部分的工作都在FormCollection中完成,傳遞給contoller方法的FormCollection對象是mvc架構自動產生的。在給實體賦值時,依次通過實體的屬性名稱取擷取對應FormCollection中的value。而就是在提取FormCollection的value時,拋出了異常,請看如下異常資訊:
Trace
System.Web.Mvc.FormCollection.GetValue(String name) +278515
System.Web.Mvc.FormCollection.System.Web.Mvc.IValueProvider.GetValue(String key) +4
System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +219
System.Web.Mvc.Controller.TryUpdateModel(TModel model, String prefix, String[] includeProperties, String[] excludeProperties, IValueProvider valueProvider) +449
System.Web.Mvc.Controller.TryUpdateModel(TModel model, IValueProvider valueProvider) +56
根據異常資訊可判斷,在調用GetValue方法時傳入了一個nul值,於是拋出了個錯誤參數的異常。起初懷疑是不是在反射時沒有許可權訪問屬性,導致返回空的屬性名稱,嘗試添加許可權控制等也沒有解決問題。也仔細查看了一下自己寫的代碼,比對<<Pro Asp.Net MVC Framework>>一書的代碼,也沒有發現差別。唯一的差別是我用的MVC版本是RC2的,而書上用的是RC1的版本,估計是新版本不支援造成的。
最後通過網上搜尋,得到的結果差點讓人跳起來。這是RC2中經過確認的一個bug,解決的方法是修改原始碼,重新編譯一個dll。所改的代碼也很簡單,把FormCollection.GetValue()中的String.IsNullOrEmpty() 去掉即可。
本以為可以平穩的運行了,可卻出現另外一個錯誤。從Html.CheckBox("chb")返回的值居然不能正常地轉為bool類型,每次運行都傳回型別轉換失敗的異常。跟蹤調試後發現從form傳遞過來的居然是"true,false"這樣的字串,難怪會轉換失敗。現在問題是為什麼會傳回這樣的值呢,介面上就只有一個Checkbox控制項。繼續查看頁面的html源碼發現,多出了一個和checkbox同名的隱藏欄位,value是false,因此每次提交之後都返回兩個值"true,false"。難道又是架構的問題?經過搜尋之後發現,依舊是架構的錯。網上給出的解釋是當選中時返回"true,false",沒選中的時候返回"false"。於是急忙嘗試了一下,果真如此。這個問題也好解決,改架構代碼、自訂一個Htmlhelper的擴充方法產生checkbox,又或者取checkbox值的時候支取第一個單詞,我採用最後一種方法。
解決以上兩個問題之後,總算能順利地跑起來了。真夠折騰,看來開源的架構還不能完全的依賴。但不過怎樣,MVC架構比起經典ASPNET來,還是很有優勢的。