【问题标题】:ASP.NET MVC 2 Custom Model Binding QuestionASP.NET MVC 2 自定义模型绑定问题
【发布时间】:2011-04-27 03:42:29
【问题描述】:

背景

我有一个付款页面,用户可以在其中从现有付款方式列表中进行选择,或指定一种新方式。下拉列表显示了以下选项:

  1. 签证 - ******1234(已保存)
  2. 万事达卡 - ******9876(已保存)
  3. [新信用卡...]
  4. [新的电子支票...]

使用 jQuery,我切换隐藏的 DIV,其中包含信息表(在选项 1 或 2 用于保存的付款方式的情况下)或表单(在 [new] 选项的情况下)。

我使用强类型类作为我的视图模型,其中包含(在简单类型中)一个 CreditCard 类和一个 Check 类。这些类中的每一个都使用数据注释验证器,因为它们在站点的其他部分中使用。

问题

当用户提交表单时,问题就出现了。我想使用模型绑定来处理 POST 值的映射,但我需要根据用户选择的选项来触发绑定和/或验证。例如,如果用户从上面的列表中选择选项 1 或 2,我不希望为 CreditCard 或 Check 对象触发模型验证(甚至可能是绑定本身)。

我研究了使用 IModelBinder 创建自定义模型绑定器以及扩展 DefaultModelBinder 并仅覆盖其中一些方法的可能性。但是,我不确定哪种方法更好,如果扩展 DefaultModelBinder,这将是覆盖的合适方法。

逻辑相当简单:

  • 如果用户选择了一种现有的付款方式,则不需要对信用卡或支票进行验证。
  • 如果用户选择其中一个选项来创建新的支付方式,则只需绑定和验证所选方式(信用卡或支票)

感觉好像扩展 DefaultModelBinder 是可行的方法,因为我希望大部分繁重的工作都由框架完成,而无需从头开始创建自定义绑定器。但是,在查看可用的重写方法时,不清楚哪个是最好的:

  1. BindProperty - 这里的问题是我基本上需要查看其中一个属性来确定应该绑定哪些其他属性。我认为我无法控制传入属性的绑定顺序,并且我不想依赖它们在 HTML 表单中设置的顺序。
  2. OnModelUpdated - 到此为止,为时已晚。数据注释的绑定验证已被触发并且 ModelState 已更新。我将不得不遍历 ModelState 并删除不相关的错误。
  3. OnPropertyValidating - 起初我认为这是我应该查看的地方,但即使为所有属性(作为测试)返回 TRUE 也会导致 ModelState 包含绑定错误。

我在应用程序的其他方面遇到过这种情况,并决定将功能拆分为单独的控制器/动作以简化流程。不过,我希望更好地了解如何处理更复杂的 UI 问题,尤其是与 MVC 模型绑定功能相关的问题。

我们将不胜感激有关此主题的任何帮助。

所有可能的值都存储在下拉列表中。使用 jQuery,我切换了表单(用于新的支付方式)和显示(用于现有的方式)

【问题讨论】:

    标签: asp.net-mvc model-binding


    【解决方案1】:

    我决定尝试完全绕过模型绑定,并在我的控制器操作中使用 FormCollection、IValueProvider 和 TryUpdateModel。

    【讨论】:

      【解决方案2】:

      您的问题听起来很专业,可以放在默认的 ModelBinder 中。

      ModelBinder 是个诱惑你的人,假装她可以解决你所有的问题。但随后你开始将 ModelState 合并在一起,并开始对嵌套对象列表做一些疯狂的事情,在你知道之前,她用离婚文件拍了你一巴掌,除了你的骨头外,什么都拿走了。

      MVC 3 承诺提供更可扩展的 ModelBinder,但根据我自己的个人经验,除非您需要更改它的超级简单,例如空 texbox 变为“”而不是 null,而不是远离您自己的实现。

      另一种方法是零碎地使用现有的 ModelBinder 功能,并使用 Ignore 方法参数之类的东西来清理:

      if( myModel.IsNewPayment )
         UpdateModel( myModel.Payment, "exclude everything else" );
      

      您建议将很多内容放入模型绑定器实际上也是业务逻辑,应该在另一层中。我用自己的 ModelBinder 做了一些疯狂的事情,现在后悔我在那里写的每一行代码。也许只有我一个人,但您确实违反了规则,并通过将业务和支付逻辑放在那里完全破坏了“单一责任主体”。

      【讨论】:

      • jfar,我不明白这是如何将业务逻辑与表示逻辑混合在一起的。我将此视为输入验证逻辑,我真正想做的是进行某种差异化验证。
      • @XSaint32 - 区分验证对我来说是业务逻辑,输入验证是这个字符串不为空,这是一个有效的日期时间,用户提供了一个价格,我想在这里警告你,区分验证并不是 modelbinder 擅长提供的
      • @jfar - 我所说的区分验证的意思是我不希望默认模型绑定器为与请求无关的字段吐出绑定错误。我看到它的方式,验证用户请求并与用户的输入交互是表示,而不是业务逻辑。如果我试图验证信用卡号本身,或者将其与被阻止的卡列表进行比较,我会同意你的看法。看看这如何简单地说,“嘿,如果用户点击选项 1,不要费心检查他是否为信用卡输入了值。”
      • 不管怎样,我决定尝试完全绕过模型绑定并在我的控制器操作中使用 FormCollection、IValueProvider 和 TryUpdateModel。
      • @jfar - 是的。我指的是自动模型绑定。 :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-22
      • 1970-01-01
      • 1970-01-01
      • 2016-03-08
      相关资源
      最近更新 更多