我在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时相同的结果。
答案 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; }
然后继续生活......我们所写的东西都比我确定的更加丑陋:)