在省略int属性时没有收到ModelState错误

时间:2014-02-12 21:37:49

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

我在MVC4中发现了一些令我困惑的功能。我有以下模型和控制器操作:

public class MyModel
{
    public int Foo { get; set; }
}

public ActionResult MyAction(MyModel model)
{
    // check ModelState.IsValid and do stuff
}

我遇到的问题是,如果我向MyAction发出GET请求并且没有传入任何参数,则ModelState.IsValid为true。如果我将Foo作为带有空字符串的param作为值传递,那么ModelState.IsValid将按预期为假(带有需要Foo的错误消息)。

所以我想我的问题是为什么当省略Foo时ModelState.IsValid为true?这是MVC中的错误还是我错过了什么?如果需要属性,则省略该属性时应该存在ModelState错误。

只是为了踢,我尝试将Foo更改为字符串并添加[Required]属性。当我这样做时,上面的两个测试都为ModelState.IsValid返回false,这也是我期望它为不可为空的int属性做的事情。在此测试之后,我将Foo更改回int并离开[Required]属性以查看是否有任何影响。仍然得到与没有[Required]属性的int时相同的结果。

2 个答案:

答案 0 :(得分:2)

西蒙在评论中所说的是正确的。

如果你没有将int传递给模型,它只是默认为0,而字符串将作为空传入并且Required检查失败。

如果要强制执行整数,则应使用可空类型。这样就可以确保它默认为null而不是0。

[Required]
public int? Foo { get; set; }

答案 1 :(得分:1)

如果我不得不在黑暗中进行刺杀,我会说这是导致这种情况发生的DefaultModelBinder类中的代码点:

    protected virtual void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor)
    {
        // need to skip properties that aren't part of the request, else we might hit a StackOverflowException
        string fullPropertyKey = CreateSubPropertyName(bindingContext.ModelName, propertyDescriptor.Name);
        if (!bindingContext.ValueProvider.ContainsPrefix(fullPropertyKey))
        {
            return;
        }

如果ValueProvider中没有提供属性名称(在最简单的情况下它只是请求参数),那么它会跳过它......显然是为了防止在某些情况下无限递归。我认为在嵌套模型的情况下这是有意义的,例如:

class Foo
{
    public Foo InnerFoo { get; set; }
}

看起来有点短视(或者我的诊断可能有点短视......)这样做,即因为这样的情况就像这样的情况。

我称之为一个错误,除非聪明的人可以纠正我。

适当的解决方法是@ Brandon的answer建议:

[Required]
public int? Foo { get; set; }

然后继续生活......我们所写的东西都比我确定的更加丑陋:)