【问题标题】:Does ModelState.IsValid=true guarantee that the passed model parameter is not null?ModelState.IsValid=true 是否保证传递的模型参数不为空?
【发布时间】:2017-10-04 08:36:10
【问题描述】:

假设我们有CreateEdit 操作方法,它们由HttpPost 赋予属性,并且它们有一个model 类型的参数,例如BlogViewModel,如下所示。

[HttpPost]
public IActionResult Create(..., BlogViewModel model)
{
....
}

[HttpPost]
public IActionResult Edit(..., BlogViewModel model)
{
....
}

在他们的身体里,我们通常做如下验证。

if(ModelState.IsValid)
{
// do something 
}

这里,do something 可以是访问model 的属性的操作。

问题

我不确定model 是否有可能变成null。如果modelnull那么do something(比如访问model的属性)会抛出异常。

我读了很多例子(来自互联网和教科书),我还没有看到有人做如下仔细检查。

if(model!=null)
{
    if(ModelState.IsValid)
    {
    // do something
    }
}

if(ModelState.IsValid)
{
    if(model!=null)
    {
    // do something
    }
}

很可能,ModelState.IsValidtrue 的条件保证了model 不是null

我的假设是否正确?恐怕我在做一个定时炸弹的假设。

【问题讨论】:

  • 如果你的代码有其他错误,模型只会是null
  • @StephenMuecke:那么是否有必要按照我上面的代码所示进行仔细检查?或者ModelState.IsValid=true 不保证model != null
  • 其实ModelState.IsValid会检查ModelState中是否添加了错误,所以在model可以为空的情况下,即使model为null,ModelState也是有效的。但是,在您的情况下,您的帖子请求中需要 BlogViewModel ,因此具有空模型的请求将引发异常。因此,在这种情况下,您无需检查模型是否为空。
  • ModelState 是有效的模型是null (只有当ModelBinder 试图设置无效的属性值时才无效)。如果请求中没有传递与模型属性名称匹配的值,或者如果您将参数命名为与模型中的属性之一相同,则模型将为 null
  • 我个人认为没有必要(并且从未见过任何例子)。在上面的第二种情况下,您将在发布之前进行更正,如果在请求中没有发送与您的模型属性匹配的值,您可以假设它是恶意用户,那么如果他们看到将由异常导致的错误页面怎么办.

标签: c# asp.net-mvc asp.net-core-mvc


【解决方案1】:

要回答您的问题,不,ModelState.IsValid 不会检查您的模型是否为空,如果发生这种情况会抛出错误。

如果您在构建请求模型时出错并且它与端点期望的不匹配,那么在 API 中很容易出现空模型。

或者其他人可能会查看您的网站,查看 API 调用并决定找点乐子,然后用没有有效模型的请求淹没您的 API。

有多种方法可以在一个地方检查空模型,例如:ModelState is valid with null model

【讨论】:

    【解决方案2】:

    什么是模型状态? ModelState 表示在 POST 期间提交给服务器的名称和值对的集合

    ModelState 中有什么? 以下是来自同一个调试器会话的这些值的样子: 每个属性都有一个 ValueProviderResult 实例,其中包含提交给服务器的实际值。

    模型状态中的验证错误... 例如:-

    [Required]
    public string FirstName { get; set; }
    
    [StringLength(50, ErrorMessage = "The Last Name must be less than {1} characters.")]
    public string LastName { get; set; }
    

    在这种情况下,如果您的 LastName 包含超过 50 个字符,则 ModelState 如果为 false,因为 vaueProvidedResult 有异常

    希望您对 ModelState 有所了解

    您的问题的答案是您可以从 modelState 处理模型

    如果模型自动为空,modelState 无效

    【讨论】:

    • OP 没有问ModelState 是什么!
    • @StephenMuecke 是的,他需要了解您可以从 modelState 处理模型的整个问题的答案
    • 如果模型自动为 null modelState 无效是错误的
    • @StephenMuecke 理论上可行吗?对不起,我从来没有遇到过这种情况
    • 如果请求中没有发送与模型属性匹配的任何内容,则DefaultModelBinder不会初始化模型,因此ModelState不会添加任何内容,它将是有效的。跨度>
    【解决方案3】:

    答案是否定的。

    ModelState 表示尝试将已发布的表单(标有BeginForm)绑定到还包括验证信息的操作方法。它带有默认的模型绑定器设置,这些设置指定应将哪些验证设置包含到视图模型中,例如RequiredAttribute,因此对必填字段的空值检查取决于存在哪些验证设置,而不是 ModelStateDictionary 本身。

    提交表单时,DefaultModelBinder 设置视图模型绑定并检查绑定的视图模型类中的每个属性是否存在验证设置(即属性)。如果提交的值与设置的条件不匹配(例如,null/标有RequiredAttribute 的属性中的空值),它将向ModelState.Errors 属性添加验证错误,随后ModelStateDictionary.IsValid 返回false,因为这取决于Errors 属性计数。这是取自ModelStateDictionary sourceIsValid检查机制:

    public class ModelStateDictionary : IDictionary<string, ModelState>
    {
        private readonly IDictionary<string, ModelState> _innerDictionary;
    
        public ICollection<ModelState> Values
        {
            get { return _innerDictionary.Values; }
        }
    
        public bool IsValid
        {
            get { return Values.All(modelState => modelState.Errors.Count == 0); 
        }
    }
    

    因此,如果所有模型属性都设置为 null/empty 而未指定 RequiredAttribute,则由于不存在验证属性且模型绑定有效,ModelStateDictionary.IsValid 的值仍为 true

    类似问题:

    ModelState.IsValid even when it should not be?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 2014-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多