为什么ASP.NET MVC默认模型绑定器很慢?完成工作需要很长时间?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (30)

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

使用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> questionsAnswerViewModel只有4个字段来存储每个答案。

事情是,点击保存按钮在这个动作方法上点击一个断点后,需要花费相当长的时间(正好10秒),也就是说,这10秒将被用在模型联编程序中。

值得一提的是,我使用Steve Sanderson的@ Html.BeginCollectionItem帮助器来实现HTTP POST的ViewModel集合属性。了解数据如何进入ViewModel(Keys):

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

我想到了4个解决方法:

  1. 只保存修改后的问题。要做到这一点我需要加载列表时,每个答案的值存储在数据属性并提交时,它与实际值进行比较<form>,因为这家伙表明这里
  2. AnswerViewModel在客户端创建JavaScript对象并将它们传递给操作方法。这是否会缓解模型绑定器?
  3. 滚动我自己的模型绑定器...但我真的不知道它是否会比ASP.NET MVC自带的默认模板更快。从我读过的默认模型绑定器做了很多反射来设置值/水合动作的模型参数,这可能是瓶颈。
  4. 使用FormCollection并通过钥匙发布数据获取每个值,如图所示手动执行验证列举在这里

你还有什么建议?

我使用选项3并实施了一个自定义模型绑定器:AnswerModelBinder : IModelBinder并将其用于特定的操作方法:

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

现在10 seconds完成了什么只需要2 seconds

  • 看起来像默认模型活页夹验证检查[ ModelState]对性能有很大影响。

我只是再次体验到了这一点:拥有一个List<Guid>作为动作参数并仅59 strings通过一次$.getJson调用就需要大约3秒钟才能在动作方法的第一行中找到一个断点。改变参数类型List<string>使整个事物在眨眼间工作。

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

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

并将其转换资源List<string>List<Guid>瞬间。

当然,ASP.NET模型绑定器有一些bug。我只是想知道它是什么...

提问于
用户回答回答于

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

扫码关注云+社区