在检查验证之前满足验证

satisfying the validation before checking the validation

假设我有以下 class

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

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

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

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

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

这个答案可能有帮助

ModelState.IsValid indicates if it was possible to bind the incoming values from the request to the model correctly and whether any explicitly specified validation rules were broken during the model binding process.

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

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

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

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

您可以在调用 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));
    }

截图如下:

另外,你也可以尝试在controller中使用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 中删除错误。