默认模型绑定器不会为IEnumerable中的可空类型进行绑定。

15

我有一个控制器动作,其定义如下:

public ActionResult ChangeModel( IEnumerable<MyModel> info, long? destinationId)

还有模型:

public class MyModel
{
    public string Name; //Gets populated by default binder
    public long? SourceId; //remains null though the value is set when invoked
}

在控制器动作中,'Name'属性被填充了,但SourceId属性保持为null。destinationId是一个long?类型的参数,也被填充。

通过MVC(版本2)源代码进行调试,DefaultModelBinder抛出了以下异常。

从类型'System.Int32'转换为类型'System.Nullable`1[[System.Int64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'失败,因为没有类型转换器可以在这些类型之间进行转换。

如果将模型更改为long而不是long?,则默认模型绑定器会设置该值。

public class MyModel
{
    public string Name {get;set;}; //Gets populated by default binder
    public long SourceId {get;set;}; //No longer long?, so value gets set
}

这是一个已知问题吗?由于MVC源代码已被优化,我无法逐步执行大部分代码。

更新:发送的请求是使用Json进行的Http POST请求,源JSon类似于 -

{"info":[{"Name":"CL1","SourceId":2}], "destinationId":"1"}
3个回答

4
也许有些晚了,但是我找到了一种解决方法。在发送数据之前,您可以将SourceId字段转换为字符串。这样您的JSON数据将会是这样的:{"info":[{"Name":"CL1","SourceId":"2"}], "destinationId":"1"}。 在我的情况下(Int32 -> decimal?,ASP NET MVC 3),这个方法起作用了。

2

我建议您在视图模型中使用属性而不是字段:

public class MyModel
{
    public string Name { get; set; }
    public long? SourceId { get; set; }
}

现在是以下请求:
/somecontroller/changemodel?destinationId=123&info[0].Name=name1&info[0].SourceId=1&info[1].Name=name2&info[1].SourceId=2

填充模型良好。


它们最初是视图模型中的属性。我已经更新了代码,请注意我正在使用JSon进行发布。 - QED
@QED,默认情况下,ASP.NET MVC 2中没有JSON请求提供程序。它是内置于ASP.NET MVC 3中的。那么你用什么来解析JSON请求到你的模型中呢? - Darin Dimitrov
我正在使用MVCFutures中可用的JsonValueProviderFactory。这些值似乎被成功地反序列化并设置在后备存储中。 - QED

1

默认的模型绑定器将所有SourceId值解析为整数。但是似乎.NET缺少从intlong?的默认类型转换器。

我会做的是实现一个类型转换器来处理这种情况。


我不确定是否需要放置类型转换器,因为操作中的另一个输入参数是 long 类型(destinationId),而且似乎已经填充好了。 - QED
@QED:是的,我知道这个问题 - 似乎问题特定于IEnumerable<>绑定。不过,那就是我会尝试的;我假设默认模型绑定器明确执行所有简单整数类型和它们的可空对应类型之间的转换,但对于集合却没有正确执行。是的,这意味着另一个可能的解决方案是覆盖默认模型绑定器... - rsenna

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接