【问题标题】:MVC Range Attribute fails when a hidden field is added to the model将隐藏字段添加到模型时,MVC 范围属性失败
【发布时间】:2015-01-22 17:21:21
【问题描述】:

我有一个父模型,其中包含子模型用于预填充视图上的字段的属性。 我想将该属性移动到它所属的子模型中,但是当我这样做时,另一个属性的范围属性会失败。 当我有一个仅用于隐藏在 EditorTemplate 上的属性时,为什么范围属性验证失败?

模型看起来像

public class ParentModel
{
    public SubModel subModel { get; set; }
}
public class SubModel
{
    public uint? DefaultValue { get; set; }

    [Required]
    [Range(1,100)]
    public uint RangedId { get; set;}

    public bool EnableRange { get; set; }
}

视图(EditorTemplate)看起来像

@model SubModel
@Html.HiddenFor(model => model.DefaultValue)
@Html.TextBoxFor(model => model.RangeId)
<script>
     $('#EnableRange').change(function() {
         if($('#EnableRange').val()){
             // remove the disabled attribute from the RangeId Field
         } else {
             // add the disabled attribute from the RangeId Field
         }
     }
</script>

控制器的样子

public ActionResult Create(TViewModel model)
{
    try
    {
        if (ModelState.IsValid)
        {
            //Do Something Meaningful
        }
        //Redisplay the view
    }
}

使用 SubModel 中的 DefaultValue 属性,即使在表单上禁用 RangeId 时,RangeId 的 Range 属性也会触发。这会导致 ModelState.IsValid 为假。 当我将 DefaultValue 属性向上移动到 ParentModel 时, RangeId 的 Range 属性不再触发(因为该字段已禁用)。这会导致 ModelState.IsValid 为真,因为 RangeId 永远不会被评估以进行验证。

【问题讨论】:

  • 如果您发布视图呈现的 html 的 sn-p 可能会有所帮助。很难理解你试图用你的 js 做什么。
  • 不清楚你在这里做什么。如果禁用控件,它不会回发,在这种情况下ModelState 将无效,因为RangedId 的值是0

标签: c# asp.net-mvc asp.net-mvc-3 mvc-editor-templates editorfor


【解决方案1】:

你认为正在发生的一切都没有发生。服务器端 Model.IsValid 不关心任何事情,也不会直接受到禁用客户端控件的影响(尽管它可能会受到间接影响,我们将在下面看到)。如果嵌套表单字段已发布并且嵌套对象具有必需的属性,则将始终进行验证。

更可能的是,这里真正的问题是,当您在子模型中有 DefaultValue 时,当您将模型提交给父模型时,模型绑定器会创建一个 SubModel 实例,因为它包含 DefaultValue 的值。当您将其移至父级并禁用 RangeId 时,没有要发布的值,因此不会创建子模型,因此不会发生验证。

即,我的猜测是,当您将 DefaultValue 移至父级时,SubModel 在回发时为空,因此因为没有要验证的实例,所以没有什么会导致验证失败,特别是因为您没有保留 EnableRange 值。

所以你确实有几个问题。首先,禁用客户端上的控件不会禁用服务器上的验证。其次,如果没有嵌套表单字段发布到服务器,则不会创建嵌套对象,也不会发生验证(因此,在这方面,如果您非常小心,可以禁用验证作为副作用)。第三,如果您确实发布了一些嵌套的表单字段,但没有发布其他字段,那么将创建嵌套对象的验证,并且验证将发生在因为它们被禁用而未发布的字段上。

【讨论】:

  • 听起来是使用IValidatableObject 接口的好理由。
  • 同意。这看起来是相当复杂的逻辑。服务器端逻辑可以在 IValidatableObject 中复制或创建一些custom attributes 来整合逻辑。
猜你喜欢
  • 1970-01-01
  • 2012-06-20
  • 2020-07-31
  • 1970-01-01
  • 2011-07-17
  • 1970-01-01
  • 2015-07-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多