現在のプロジェクトでは、クライアントはWizard
(一度に1つの質問)とListing
(一度にすべての質問)を1つの方法で使用するという2つの方法でアンケートに回答する可能性を求めました形。どちらの方法も既に実装されています。なぜASP.NET MVCのデフォルトモデルバインダーが遅いのですか?
質問はAJAXを使用してマニュアルの章ごとにデータベースから読み込まれます(これは超高速です)。現時点で最大の章は230
(4つのHTML入力フィールド - 入力/テキスト、選択など)の質問があります。ユーザーがListing
形式で回答する章を選択した場合、<form>
には、約920
のフィールドがサーバーに送信されます。
私はjQueryのserialize
方法でデータを渡すAJAX POSTリクエストをやってる:
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秒間がモデルバインダーに費やされていると考えられます。
重要なことは、Steve Sandersonの@Html.BeginCollectionItem helperを使用して、HTTP POSTからViewModelコレクションプロパティを作成する際に役立つことです。データはViewModelに(キー)で取得する方法を参照してください:
あなたは、私がこれを最適化するためにやろうとすることができるものを知っていますか?
保存バックのみ変更質問:
は、私は約4回避策を考えました。これを行うには、リストをロードするときにデータ属性に各回答値を格納し、<form>
を提出するときに実際の値と比較する必要があります。hereです。クライアント側で
AnswerViewModel
JavaScriptオブジェクトを作成し、アクションメソッドに渡します。モデルバインダーを緩和しますか?私のモデルバインダーをロールバックしますが、ASP.NET MVCに付属するデフォルトのバインダーよりも高速であるかどうかはわかりません。私が読んだことから、デフォルトのモデルバインダーは、値を設定するための多くの反省を行い、アクションのモデルパラメータを水和させ、これがボトルネックになる可能性があります。
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>
を有し、かつ$.getJson
呼び出しを通じてのみ59 strings
を渡すの1行目にブレークポイントをヒットする〜3秒を取っていましたアクションメソッド。パラメータタイプをList<string>
に変更すると、目の瞬きの中で全体が機能します。
興味深い事実は、アクションメソッドの内部で、私はこれをしなかったということです。
List<Guid> userIds = resources.Select(Guid.Parse).ToList();
、それが瞬時にList<Guid>
にリソースList<string>
を変換します。
確かに、ASP.NETモデルバインダーにはバグがあります。私はちょうどそれが何であるか知りたいと思います... :)
です。いくつの質問をサーバーに送信していますか?モデルバインダーは、要求からの入力を解析することについて非常に汎用的であるようにするために、多くのコードを使用します。私はあなたのケースでは解決する最善の方法は、あなたが取った道だったと思います。 – OdeToCode
@OdeToCode見ていただきありがとうございましたScott ...ありがとうございます。あなたはカスタムモデルバインダーのアプローチに同意します。この特定のケースでは、230の質問をサーバーに送信しています。私もオプション#1を行うと、もっと速くなると思う...;)JavaScriptはかなり速いので2秒ではなく1秒かもしれない。これをテストしなければなりません。 –
@OdeToCodeコードを補完して回避策を実装しました#1質問をロードするときに上記のように言及しました。データ属性に現在の値を入力/選択し、保存するときには、属性。私はjQueryのフィルタ関数を使ってこれを助けます。今すぐ保存は瞬間的です。 :-) jQueryコードは非常に高速です! –