当我接受一个对象进入我今天的一个动作时,我发现如果我的对象有一个可以为空的结构的属性,并且我填充了它,我得到了一个ArgumentNullException。
这就是它的样子(极端简化,使用GET创建一个更简单的例子):
//Action
[HttpGet]
public JsonResult Test(SuperClass model)
{
return Json("The will not work...", JsonRequestBehavior.AllowGet);
}
//...
public class SuperClass
{
public string ArbitraryProperty { get; set; }
public SpecialDate SpecialDateA { get; set; }
//This seems to be the problem
public SpecialDate? SpecialDateB { get; set; }
}
public struct SpecialDate
{
public int? Year { get; set; }
public int Month { get; set; }
public int Day { get; set; }
}
现在,如果我调用以下网址: http://EXAMPLE.COM/Home/Test/?ArbitraryProperty=Foo&SpecialDateA.Year=2014&SpecialDateA.Month=8&SpecialDateA.Day=12&SpecialDateB.Year=2015&SpecialDateB.Month=9&SpecialDateB.Day=10 然后我设置了我真正需要的所有数据,但是我在System.ComponentModel.DataAnnotations.ValidationContext构造中得到了一个ArgumentNullException。
因此,将可为空的struct属性设置为MVC5中的action参数不起作用。在这种情况下,我只是为一个类切换结构,但是为了将来使用它会很有趣,知道为什么这不起作用。
修改
为了澄清,在我的请求中反序列化对象时,MVC框架抛出了ArgumentNullException(参见示例URL)。 上面代码中的Test操作放在我的HomeController中,在这个例子中执行永远不会进入方法,在此之前抛出错误(调用示例URL时)。
编辑2: 关于@Shoe的评论,我还测试了以下网址: http://EXAMPLE.COM/Home/Test/?ArbitraryProperty=Foo&SpecialDateA.Year=2014&SpecialDateA.Month=8&SpecialDateA.Day=12&SpecialDateB.Value.Year=2015&SpecialDateB.Value.Month=9&SpecialDateB.Value.Day=10
我所做的是尝试通过 Value 属性分配SpecialDateB,但它似乎也不起作用。
编辑3:
为了澄清更进一步,这是一个更简单的问题示例:
这有效:
[HttpGet]
public JsonResult Fest(int? foo)
{
return Json("This will work", JsonRequestBehavior.AllowGet);
}
这不起作用:
[HttpGet]
public JsonResult Fest(Fee fee)
{
return Json("This won't work...", JsonRequestBehavior.AllowGet);
}
...
public class Fee
{
public int? Foo { get; set; }
}
答案 0 :(得分:2)
ASP.NET MVC的默认模型绑定器使用Activator.CreateInstance(System.Type)
来创建模型及其属性,并且它没有处理Nullable<>
类型的特殊魔法。
由于您正在使用Nullable<SpecialDate>
作为&#34; SpecialDateB&#34;,因此MVC在调用Activator.CreateInstance(System.Type)
时会获得空引用,因为它没有初始值。然后,MVC更新触发模型验证的模型状态。
这就是崩溃的原因。
MVC用于验证的System.ComponentModel.DataAnnotations.ValidationContext
(MSDN reference here)要求&#34;实例&#34;参数(在这种情况下,&#34; SpecialDateB&#34;属性的值)不为空,否则抛出ArgumentNullException
。
简而言之,MVC不支持Nullable<>
类型的参数(或参数&#39;属性,如您的情况)。
我建议使用类而不是结构,直到MVC团队修复了对Nullable<>
的支持。
修改强>
澄清我的答案:我的意思是声称&#34; MVC不支持参数的Nullable<>
类型&#34;仅针对所呈现的案例。像int
,DateTime
等简单类型可以作为可以为空的参数使用。但是,只要您将复杂类型创建为结构并尝试将其用作可为空的参数,MVC就无法处理它。无论您是为其指定值,还是它是可选的。很抱歉我的上述答案不清楚。