【问题标题】:satisfying the validation before checking the validation在检查验证之前满足验证
【发布时间】:2020-12-16 07:22:12
【问题描述】:

假设我有以下课程

class A
{
  [Required]
  public string Name {get; set;}
  [Required]
  public string NickName {get; set;}
  [Required]
  public string UserId {get; set;}
}

从表单中,我只将名称和昵称传递给控制器​​,在检查模型状态之前,我只需将用户 ID 分配给 UserId 属性,如下所示

    [HttpPost]
    public IActionResult Save(A model)
    {
        model.UserId = User.GetLoggedInUserId<string>();
        if (!ModelState.IsValid)
        {
           return View(model);
        }        
    }

即使我在检查模型状态之前分配了用户 ID,它仍然返回验证状态 false 并抱怨用户 ID。解决这个问题的一种方法是创建一个视图模型,这会使事情变得更加复杂,因为将视图模型中的值分配给它自己的类。 知道如何解决这个问题。

注意:问题不仅在于类中的用户 ID,还可能有其他属性可能不会从表单传递到控制器,并且值可能会从控制器分配给它们

【问题讨论】:

    标签: c# validation view controller asp.net-core-mvc


    【解决方案1】:

    您可以在调用ModelState.IsValid 之前尝试remove 模型验证中的“UserId”。像这样的代码:

        [HttpPost]
        public IActionResult CreateA(A a)
        {
            var state1 = ModelState.IsValid;  // false
            ModelState.Remove("UserId");      //using Remove method to remove the specified object from the model-state dictionary.
            var state2 = ModelState.IsValid;  // true
            
            a.UserId = "SN1001";
              
            if (ModelState.IsValid)
            {
                var data = a.UserId;
            }
            return RedirectToAction(nameof(Index));
        }
    

    截图如下:

    此外,您还可以尝试使用TryValidateModel() 方法在控制器中再次验证模型,代码如下:

        [HttpPost]
        public IActionResult CreateA(A a)
        {
            var state1 = ModelState.IsValid;  // false 
            
            ModelState.Remove("UserId");
    
            a.UserId = "SN1001";
    
            if (!TryValidateModel(a, nameof(a)))
            { 
                var state2 = ModelState.IsValid;              
            }
    
            if (ModelState.IsValid)
            {
                var data = a.UserId;
            }
            return RedirectToAction(nameof(Index));
        }
    

    结果如下:

    参考:Model State Rerun validation

    编辑

    [注意]如果ModelState.IsValid首先是false,在使用TryValidateModel方法重新运行验证之前,我们必须从ModelState中删除错误。

    【讨论】:

      【解决方案2】:

      您还可以使用具有默认值的隐藏字段传递UserId 字段的值,例如:

      @Html.HiddenFor(m =&gt; m.UserId, new { @Value = User.Identity.Name });

      【讨论】:

      • 不错的一个!以巧妙的方式覆盖绑定验证,提供默认值。但是如果它是可选的并且实际上有一个可能的值可以输入,那就很难了。
      • 从表单中传递用户 ID 可能会危及应用程序的安全性,我认为这不是一个好主意
      • 然后使用伪值来欺骗验证器并像在Save 方法中那样覆盖这个值。我想不出任何其他方式来解决这个问题。您必须创建一个 ViewModel 类或使 UserId 不是必需的。
      【解决方案3】:

      这个答案可能对What does ModelState.IsValid do?有帮助

      ModelState.IsValid 指示是否可以将来自请求的传入值正确绑定到模型,以及在模型绑定过程中是否违反了任何明确指定的验证规则。

      没有办法解决这个问题。如果您不需要此验证,则将其与属性一起删除,并使用代码添加适当的值处理逻辑。

      isValid 只会在绑定时间验证状态,仅此而已。

      【讨论】:

        猜你喜欢
        • 2020-02-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多