2013-02-19 94 views
16

在當前的項目中,客戶要求以兩種方式回答調查問卷的可能性:一次使用Wizard(一次提出一個問題)和Listing(一次提出所有問題)形成。這兩種方式已經實施。爲什麼ASP.NET MVC的默認Model Binder速度很慢?需要很長時間才能完成工作

使用AJAX(這是超快速),每個手冊的章節都會從數據庫加載這些問題。目前最大的章節有230問題(每個問題有4個HTML輸入字段 - 輸入/文本,選擇等)。如果用戶選擇此章節以Listing格式回答,則<form>將包含約920字段以發佈到服務器。

我在做一個AJAX POST請求傳遞的數據與jQuery的serialize方法:

data: $("#questions :input").serialize() 

這種序列化發生207.143ms完成。我在Firefox中使用Firebug這個值調試:

console.profile(); 
$("#questions :input").serialize(); 
console.profileEnd(); 

再次,這是超級快...

以下操作方法時,保溼接收到的數據的問題就來了:

public async Task<ActionResult> ListSaveAsync(IEnumerable<AnswerViewModel> questions) 

如您所見,發佈的數據是綁定到IEnumerable<AnswerViewModel> questions的數據。 AnswerViewModel只有4個字段來存儲每個答案。

事情是,在點擊保存按鈕在這個動作方法上點擊一個斷點後,需要花費相當長的時間(正好是10秒),也就是說,這10秒將被用在模型聯編程序中。

需要注意的一個重要的事情是,我使用Steve Sanderson的@Html.BeginCollectionItem helper來幫助實現HTTP POST的ViewModel集合屬性。看到這些數據的視圖模型(鑰匙)如何到達:

enter image description here

你知道我可以嘗試做優化呢?

我想約4解決方法:

  1. 救回來只有修正的問題。要做到這一點,我需要在加載列表時將每個答案值存儲在數據屬性中,並在提交<form>時將其與實際值進行比較,因爲此人建議here

  2. 創建AnswerViewModel客戶端上的JavaScript對象並將它們傳遞給操作方法。這是否會緩解模型綁定器?

  3. 滾動我自己的模型綁定器......但我真的不知道它是否會比ASP.NET MVC默認的快。從我讀過的默認模型綁定器中做了很多反射來設置值/水合動作的模型參數,這可能是瓶頸。

  4. 使用FormCollection並通過發佈的數據枚舉按鍵獲取每個值並手動執行驗證,如here所示。

您還建議了什麼?


更新1

我去選項3,實現了自定義的模型綁定:AnswerModelBinder : IModelBinder並在具體操作方法使用它:

public async Task<ActionResult> ListSaveAsync(
      [ModelBinder(typeof(AnswerModelBinder))]List<AnswerViewModel> questions) 

現在什麼了10 seconds完成只需要2 seconds

  • 看起來像默認模型活頁夾驗證檢查[ModelState]對性能有很大影響。

更新2

我只經歷過一次:具有List<Guid>作爲操作參數,只有通過59 strings通過$.getJson呼叫正在採取〜3秒命中一個斷點在一號線行動方法。將參數類型更改爲List<string>使整件事情在眨眼之間起作用。

一個有趣的事實是,該操作方法裏面我這樣做:

List<Guid> userIds = resources.Select(Guid.Parse).ToList(); 

並把它轉換的資源List<string>List<Guid>瞬間。

肯定有一些與ASP.NET模型綁定器錯誤。我只是想知道它是什麼... :)

+1

很抱歉的緩慢回覆,Leniel。您發送給服務器的問題有多少?模型聯編程序使用大量代碼來試圖解析來自請求的輸入的通用性。我認爲在你的情況下,最好的解決辦法就是你走的路。 – OdeToCode 2013-02-21 21:44:47

+0

@OdeToCode感謝Scott的採訪......不錯,您同意自定義模型活頁夾的方法。在這個特定的情況下,我向服務器發送了230個問題。如果我也選擇了#1選項,我認爲它會更快......;)可能是1s而不是2s,因爲JavaScript相當快。必須測試這個。 – 2013-02-21 22:53:45

+0

@OdeToCode只補充了代碼並實現瞭解決方法#1上面提到的=>加載問題時,我將每個輸入/選擇當前值放入數據屬性中,當保存時,我將當前值與數據中先前的值進行比較屬性。然後,我使用jQuery的過濾功能來幫助解決這個問題。現在保存是即時的。 :-) jQuery代碼非常快! – 2013-02-22 04:58:54

回答

1

這可能不是你正在尋找的答案,但它可能會有所幫助。不要使用FormCollection,而是嘗試讓控制器方法接受簽名中的模型並使用Ajax.BeginForm()。這將消除對序列化的需求,並允許MVC完成它的工作。此外,有一個類型問題列表模型可能值得研究。這種方法似乎也不需要遍歷帖子中的值,因爲它們已經在模型中了。

+0

感謝您的輸入安東尼。對此,我真的非常感激。我得試試這個... – 2013-05-24 17:02:45

0

我還沒有嘗試過,但是當我使用整數索引時,綁定器在綁定到IEnumerable時沒有問題。既然你實際上沒有使用這些Guids,我會用整數替換它們。 (0,1,2 ...)

我想你可以在呈現窗體或使用JS的頁面上輕鬆地做到這一點。

相關問題