C# 当可为Null的结构

C# 当可为Null的结构,c#,asp.net-mvc-5,C#,Asp.net Mvc 5,当我今天接受一个对象到我的一个动作中时,我发现如果我的对象有一个可为null的结构的属性,并且我填充了它,我会得到一个ArgumentNullException 这就是它看起来的样子(在极端简化中,使用GET创建一个更简单的示例): 现在,如果我调用以下URL: 然后我设置了我真正需要的所有数据,但在System.ComponentModel.DataAnnotations.ValidationContext构造中得到了ArgumentNullException 但是,以下URL将起作用: 因此

当我今天接受一个对象到我的一个动作中时,我发现如果我的对象有一个可为null的结构的属性,并且我填充了它,我会得到一个ArgumentNullException

这就是它看起来的样子(在极端简化中,使用GET创建一个更简单的示例):

现在,如果我调用以下URL: 然后我设置了我真正需要的所有数据,但在System.ComponentModel.DataAnnotations.ValidationContext构造中得到了ArgumentNullException

但是,以下URL将起作用:

因此,在MVC5中将nullable struct属性设置为操作参数是行不通的。在本例中,我将只切换一个类的结构,但对于将来的使用来说,了解为什么这样做不起作用是很有趣的

编辑:

[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; }
}
为了澄清这一点,MVC框架在反序列化请求中的对象时抛出ArgumentNullException(参见示例URL)。 在本例中,上述代码中的测试操作放在my HomeController中,执行过程永远不会进入方法,在此之前会抛出错误(调用示例URL时)

编辑2: 关于@Shoe的评论,我还测试了以下URL:

我所做的是试图通过SpecialDateB的属性分配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; }
}
要进一步澄清,这里有一个更简单的问题示例:

这是有效的:

[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; }
}
这不起作用:

[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; }
}

ASP.NET MVC的默认模型绑定器使用
Activator.CreateInstance(System.Type)
来创建模型及其属性,并且它没有处理
Nullable
类型的特殊魔法

由于对“SpecialDateB”使用了
Nullable
,MVC在调用
Activator.CreateInstance(System.Type)
时会得到一个空引用,因为它没有初始值。MVC然后更新触发模型验证的模型状态

这就是坠机的原因

MVC用于验证的
System.ComponentModel.DataAnnotations.ValidationContext
()要求“instance”参数(在本例中为“SpecialDateB”属性的值)不为null,否则会引发
ArgumentNullException

简而言之,MVC不支持参数的
Nullable
类型(或参数的属性,如您的情况)

我建议使用类而不是结构,直到MVC团队固定支持
Nullable

编辑:

[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; }
}

为了澄清我的答案:我所说的“MVC不支持参数的
Nullable
类型”仅适用于所介绍的情况。像
int
DateTime
等简单类型可以作为可空参数使用。但是,当您创建一个复杂类型作为结构并尝试将其用作可为空的参数时,MVC就无法处理它。无论是为其指定值还是可选值。对不起,我上面的回答不清楚。

那么问题是什么?此外,您可能希望显示一些初始化此操作的代码,或者至少显示引发异常和异常消息的方法。问题是为什么会引发异常,执行是URL(虽然URL是假的,但其结构是正确的,它调用测试操作)。您能显示行吗,反序列化是由MVC框架在路由过程中调用服务时运行的,所以我还没有编写它。这就是我感到困惑的原因。我很确定问题在于可空结构的工作方式
Value
SpecialDateB
(不是日、月、年)上的唯一属性,它是不可变的。我还认为,虽然您的第一个结构不会生成错误,但您的属性不会被传递。类肯定是最好的选择,因为可变结构几乎总是一个坏主意。不过MVC确实支持可空类型。您可以使用
int?
Datetime?
作为参数。您可以使用int?作为一个参数,它工作得很好。这不是我的问题。我的问题是,当您使用一个对象作为参数,而该对象使用的是可为空的属性时,它就会中断。这就是为什么这么奇怪。