asp.net-mvc - 验证传播到相关对象

标签 asp.net-mvc validation model-binding

我有一个这样的模型:

public class Person
{
    public int ID { get; set; }

    [Required(ErrorMessage="Name cant be empty")]
    public string Name { get; set; }

    public Person Friend { get; set; }
}

我想创建一个新的 Person,并使用强类型 HtmlHelper 制作一个包含字段的表单

  • 身份证
  • 姓名
  • 好友 ID(包含 <option value="Friend.ID">Friend.Name</option> 等选项的下拉列表

alt text

发布表单时,我的 Controller 接收一个 Person 对象 ( p ),该对象使用默认的 modelbinder 进行绑定(bind)。明确地说,模型绑定(bind)器执行以下操作:IDName属性按预期绑定(bind)。 Friend设置为新的Person实例 ID等于我在下拉列表中选择的人的 ID。 Friend.Name的值为null因为我没有在表单中提供它的值。

问题:我想要RequiredAttribute开火Name文本框,如果它是空的 - 确实如此。问题是它也会在 Friend 上触发的名称属性。因此,当我发布并填写所有字段时,我发现 ModelState 无效,错误是 p.Friend.Name是必须的。 alt text

我该如何解决这个问题?当然,在这种情况下,我不想验证 Friend的属性。我想到过:

  1. 使用 ViewModels 来表达我的观点,这会以某种方式解决我的问题。我还没有尝试过,因为我觉得对于这么简单的问题我真的不需要这样做
  2. 将 friend 的 ID 作为单独的参数发送,friend_id ,并绑定(bind)Friend手动属性。只有IDName发布者的属性已绑定(bind),我手动设置Friend属性(property)。这涉及获取 Friend使用 friend_id 从我的存储库中使其成为“真正的”Person 对象。
  3. 检查 ModelState 并删除我知道的错误不算数。这完全是错误的并且不可扩展(如果我添加例如 SecondFriend 属性,则必须记住这样做

我觉得选项 2 是最可行的,但理想情况下我希望它是自动的。此外,我无法使用强类型帮助程序,如 friend_id文本框'name属性必须与操作方法的参数名称匹配。

我觉得我错过了一些可以让这件事变得更容易的点。希望我是对的。虽然我认为使用 ViewModel 有点乏味,但这是正确的做法,请告诉我。

编辑

现在使用 ViewModels 解决了问题 ID , NameFriend_id其属性和与 Person 相同的验证属性模型。然后我映射 IDName值变为新的Person实例。然后通过从存储库加载指定的好友来设置 Friend 属性。喜欢newPerson.Friend = repository.Get(viewModel.Friend_id)

当我有时间时,我计划仔细观察 AutoMapper “自动”执行此操作。

最佳答案

问题是模型状态字典键只有属性名称作为键。因此,在您的情况下,其中有两个具有相同的 key :Person 上的 NameFriend 上的 Name .

我一直在努力让这样的事情发挥作用。如果键名称具有类似于 VarName.PropertyName 的表示法,那就最好了。在这种情况下它会起作用,因为你有两个不同的:

  • p.Name
  • p.Friend.Name

拥有 ClassName.PropertyName 是行不通的,因为您可能有两个类型相同但名称不同的操作参数。

但是应该如何解决这个问题呢?一种方法是创建您自己的操作过滤器来执行模型验证并填充模型状态错误(首先将其全部清除)。这也意味着您必须使用 Html 扩展方法的非 lambda 版本。因此,您必须使用 Html.TextBox 扩展程序并提供自定义键,而不是 Html.TextBoxFor

为了使 View 方面的内容更加通用,您当然可以编写自己的 Html 扩展重载(您使用的扩展重载),该重载将采用参数名称的附加参数,例如:

Html.TextBoxFor("p", model => model.Friend.Name);

然后会生成

<input type="text" name="p.Friend.Name" id="p_Friend_Name" />

相信我,默认模型绑定(bind)器将能够使用这些类型的输入名称。它具有参数名称及其属性的知识。

关于asp.net-mvc - 验证传播到相关对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3702496/

相关文章:

orchardcms - Orchard cms : how to add media picker field to anew module

forms - Flutter GetX 表单验证

c# - 使用默认行为将模型绑定(bind)到接口(interface)

asp.net-mvc - 如何让 ASP.NET MVC 3 使用来 self 网站的外部程序集的 View (aspx、ascx)文件?

asp.net-mvc - 如何接受电子邮件地址作为路由值?

c# - 如何在 Asp.net MVC 中实现对象数据库

regex - 为什么人们使用正则表达式进行电子邮件和其他复杂的验证?

java - 使用 Hibernate 进行数据验证

c# - 如何从命令对象中访问整个 ViewModel

asp.net-mvc - HiddenFor(x => x.Id) 由 UrlParameter 而不是 ViewModel 填充