为什么ASP.NET MVC默认的Model Binder很慢?它需要很长时间才能完成它的工作

Len*_*rri 18 data-binding asp.net-mvc performance ienumerable post

在当前项目中,客户要求以两种方式回答调查问卷的可能性:一次使用Wizard(一次一个问题)和Listing(一次性所有问题).两种方式都已实施.

使用AJAX按照手册的章节从数据库加载问题(这非常快).目前最重要的章节有230问题(每个都有4个HTML输入字段 - 输入/文本,选择等).如果用户选择此类章节以Listing格式回答,<form>则将包含920要发布到服务器的大约字段.

我正在做一个使用jQuery serialize方法传递数据的AJAX POST请求:

data: $("#questions :input").serialize()
Run Code Online (Sandbox Code Playgroud)

此序列化需要207.143ms完成.我在Firefox中使用Firebug调试了这个值:

console.profile();
$("#questions :input").serialize();
console.profileEnd();
Run Code Online (Sandbox Code Playgroud)

这又是超级快......

在对以下操作方法收到的数据进行保湿时会出现问题:

public async Task<ActionResult> ListSaveAsync(IEnumerable<AnswerViewModel> questions)
Run Code Online (Sandbox Code Playgroud)

如您所见,发布的数据是绑定到的数据IEnumerable<AnswerViewModel> questions.AnswerViewModel只有4个字段来存储每个答案.

问题是,在单击"保存"按钮以触发此操作方法的断点之后需要相当长的时间(精确地为10秒),也就是说,大概在模型绑定器中花费了10秒.

值得一提的是,我正在使用Steve Sanderson的@ Html.BeginCollectionItem助手来帮助从HTTP POST实现ViewModel集合属性.查看数据如何在ViewModel(Keys)中获取:

在此输入图像描述

你知道我可以尝试做些什么来优化这个吗?

我想过4个解决方法:

  1. 仅保存修改后的问题.要做到这一点我需要加载列表时,每个答案的值存储在数据属性并提交时,它与实际值进行比较<form>,因为这家伙表明这里.

  2. AnswerViewModel在客户端创建JavaScript对象并将其传递给action方法.这会减轻Model Binder吗?

  3. 滚动我自己的模型绑定...但我真的不知道它是否会比ASP.NET MVC附带的默认绑定更快.从我所看到的,默认模型绑定器做了很多反思来设置值/水合动作的模型参数,这可能是瓶颈.

  4. 使用FormCollection并通过钥匙发布数据获取每个值,如图所示手动执行验证列举在这里.

你还有什么建议?


更新1

我使用选项3并实现了一个自定义模型绑定器:AnswerModelBinder : IModelBinder并在特定的操作方法中使用它:

public async Task<ActionResult> ListSaveAsync(
             [ModelBinder(typeof(AnswerModelBinder))]List<AnswerViewModel> questions)
Run Code Online (Sandbox Code Playgroud)

现在需要10 seconds完成的只需要2 seconds.

  • 看起来默认的模型绑定器验证检查[ ModelState]对性能有很大影响.

更新2

我刚刚再次体验过它:拥有一个List<Guid>动作参数并且仅59 strings通过一个$.getJson调用传递大约需要3秒才能在动作方法的第一行中击中一个断点.改变参数类型List<string>使整个工作在眨眼间工作.

一个有趣的事实是,在动作方法中我做了这个:

List<Guid> userIds = resources.Select(Guid.Parse).ToList();
Run Code Online (Sandbox Code Playgroud)

它将资源瞬间转化List<string>List<Guid>现实.

当然,ASP.NET模型绑定器存在一些问题.我只是想知道它是什么...... :)

Ant*_*son 1

这可能不是您正在寻找的答案,但可能会有所帮助。尝试让控制器方法接受签名中的模型并使用 Ajax.BeginForm(),而不是使用 FormCollection。这将消除序列化的需要,并允许 MVC 完成它的工作。此外,具有问题类型列表的模型可能值得研究。这种方法似乎也消除了迭代帖子上的值的需要,因为它们已经存在于模型中。