20

現在のプロジェクトで、クライアントは 2 つの方法でアンケートに回答する可能性を求めました。単一のフォームで (一度にWizard1 つの質問) と(一度にすべての質問) を使用します。Listingどちらの方法もすでに実装されています。

質問は、AJAX を使用してマニュアルの章ごとにデータベースからロードされます (これは非常に高速です)。現時点で最大の章には230質問があります (それぞれに 4 つの HTML 入力フィールド (入力/テキスト、選択など) があります)。ユーザーがそのような章を選択してListingフォーマットで回答すると、サーバーに投稿される<form>at about フィールドが含まれます。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> questionsAnswerViewModel各回答を保存するフィールドは 4 つだけです。

問題は、[保存] ボタンをクリックしてからこのアクション メソッドのブレークポイントに到達するまでにかなりの時間 (正確には 10 秒) かかることです。

重要なことは、HTTP POST から ViewModel コレクション プロパティを具体化するときに、 Steve Sanderson の@Html.BeginCollectionItem ヘルパーを使用していることです。ViewModel (キー) でデータがどのように取得されるかを確認します。

ここに画像の説明を入力

これを最適化するために私ができることを知っていますか?

私は4つの回避策について考えました:

  1. 変更された質問のみを保存します。<form>これを行うには、リストをロードするときに各回答値を data-attribute に保存し、この男がここで提案しているように、送信時に実際の値と比較する必要があります。

  2. AnswerViewModelクライアント側で JavaScript オブジェクトを作成し、アクション メソッドに渡します。これは Model Binder を軽減しますか?

  3. 独自のモデル バインダーを展開しますが、ASP.NET MVC に付属する既定のバインダーよりも高速になるかどうかはわかりません。私が読んだことから、デフォルトのモデルバインダーは多くのリフレクションを行って値を設定したり、アクションのモデルパラメーターを水和したりしますが、これがボトルネックになる可能性があります。

  4. ここに示すように、投稿されたデータを使用FormCollectionして列挙し、キーごとに各値を取得し、手動で検証を実行します

他に何を提案しますか?


更新 1

オプション 3 をAnswerModelBinder : IModelBinder使用し、カスタムの Model Binder を実装しました。それを特定のアクション メソッドで使用しました。

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

10 seconds、完了するのにかかったものは2 seconds.

  • デフォルトのモデル バインダーの検証チェック [ ModelState] がパフォーマンスに大きな影響を与えているようです。

更新 2

もう一度経験しました。アクション パラメータとして a を持ち、呼び出しのみをList<Guid>渡すと、アクション メソッドの 1 行目のブレークポイントに到達するのに約 3 秒かかりました。パラメータのタイプを変更して、すべてが一瞬で機能するようにしました。59 strings$.getJsonList<string>

興味深い事実は、アクション メソッド内で次のようにしたことです。

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

List<string>そして、リソースをList<Guid>瞬時に変換します。

確かに、ASP.NET モデル バインダーにはバグがあります。私はそれが何であるかを知りたいだけです... :)

4

3 に答える 3

2

ベンチマーク結果が非常に高速な ServiceStack JsonSerializer を使用できます。ドキュメントは http://mono.servicestack.net/docs/text-serializers/json-serializer で、ベンチマークは http://mono.servicestack.net/benchmarksです。 /

于 2014-03-21T09:11:16.607 に答える
1

これはあなたが探している答えではないかもしれませんが、役立つかもしれません。FormCollection を使用する代わりに、コントローラー メソッドが署名でモデルを受け入れ、Ajax.BeginForm() を使用するようにしてください。これにより、シリアル化の必要がなくなり、MVC がその作業を実行できるようになります。また、タイプ Question の List を持つモデルを持つことは、検討する価値があるかもしれません。このアプローチは、投稿の値が既にモデルに含まれているため、値を繰り返し処理する必要がないようにも見えます。

于 2013-05-24T12:26:01.963 に答える
0

私はこれを試していませんが、整数インデックスを使用すると、バインダーは IEnumerable へのバインドに問題はありませんでした。実際にはこれらの Guid を使用していないので、整数に置き換えます。(0,1,2...)

フォームをレンダリングするページまたは JS を使用して、これを簡単に行うことができると思います。

于 2014-03-11T10:25:55.150 に答える